import asyncio
import pygame
import sys
import os
from typing import Optional, Dict, Any, Tuple
from game_client import GameClient
from ui.renderer import GameRenderer
from ui.animations import AnimationManager, AttackAnimation, DamageFlash, HealFlash


class CardGame:
    """卡牌游戏主类"""
    
    def __init__(self):
        self.client = GameClient()
        self.renderer = GameRenderer()
        self.animation_manager = AnimationManager()
        
        # Set error callback for game client
        self.client.set_error_callback(self.show_message)
        
        # Set animation callback for game client
        self.client.set_animation_callback(self.handle_animation)
        
        # Set game over callback for game client
        self.client.set_game_over_callback(self.handle_game_over)
        
        # Set Flag choice callback for game client
        self.client.set_flag_choice_required = self.set_flag_choice_required
        
        # Set music control methods for game client
        self.client.start_background_music = self.start_background_music
        self.client.stop_background_music = self.stop_background_music
        
        # 游戏状态
        self.connected = False
        self.player_id = None
        self.room_id = None
        self.server_url = None
        
        # UI状态
        self.input_mode = "server_url"  # server_url, room_manager, deck_selection, playing, custom_deck_editor
        self.server_url_input = ""
        self.room_id_input = ""
        self.selected_cards = []  # 换牌阶段选中的卡牌
        self.selected_deck = None  # 选择的卡组
        
        # 房间管理相关状态
        self.rooms_list = []  # 房间列表数据
        self.selected_room_id = None  # 用户在左侧选中的房间ID
        self.create_room_input = ""  # 创建房间时输入的房间号
        
        # 自定义卡组编辑器状态
        self.custom_deck_name = ""  # 卡组名称
        self.custom_deck_description = ""  # 卡组描述
        self.custom_deck_cards = {}  # 已选择的卡牌 {card_id: count}
        self.selected_card_for_count = None  # 当前选择用于设置数量的卡牌
        self.card_count_input = ""  # 数量输入
        self.card_count_input_active = False  # 数量输入框是否激活
        self.name_input_active = False  # 名称输入框是否激活
        self.desc_input_active = False  # 描述输入框是否激活
        self.card_category = "All"  # 当前卡牌分类
        # 动态生成分类选项，基于server/cards文件夹结构
        self.card_category_options = self._generate_card_categories()
        
        # 卡组管理相关状态
        self.editing_deck_filename = ""  # 当前编辑的卡组文件名(用于覆盖保存)
        self.show_deck_list = False  # 是否显示卡组列表弹出层
        self.custom_decks_list = []  # 自定义卡组列表
        
        # 游戏结束相关状态
        self.game_over_result = None  # 游戏结束结果
        
        # 交互状态机
        self.interaction_state = "IDLE"  # IDLE, CARD_SELECTED, TARGET_SELECTION
        self.pending_card = None  # 待处理的卡牌ID
        self.pending_card_data = None  # 待处理的卡牌数据
        self.pending_action = None  # "SUMMON", "USE_ITEM", "ATTACK"
        self.pending_position = None  # 待召唤的位置
        self.selected_target = None  # 选中的目标ID
        self.valid_targets = []  # 当前可选择的有效目标
        
        # 消息提示系统
        self.message_text = ""  # 当前显示的消息
        self.message_color = None  # 消息颜色
        self.message_timer = 0  # 消息显示时间计时器
        self.message_duration = 3.0  # 消息显示持续时间（秒）
        
        # 卡牌详情显示系统
        self.card_tooltip = None  # 当前显示的卡牌详情
        self.tooltip_timer = 0  # 详情显示时间计时器
        self.tooltip_duration = 5.0  # 详情显示持续时间（秒）
        
        # Flag道具选择系统
        self.flag_choice_required = False  # 是否需要Flag选择
        self.flag_choices = []  # Flag的选择选项
        self.pending_flag_card = None  # 待处理的Flag卡牌
        
        
        # 输入框
        self.input_font = pygame.font.Font(None, 32)
        
        # 时钟
        self.clock = pygame.time.Clock()
        self.running = True
        
        # 背景音乐
        self.background_music = None
        self.music_playing = False
        self.load_background_music()
    
    def load_background_music(self):
        """加载背景音乐"""
        try:
            music_path = os.path.join(os.path.dirname(__file__), "assets", "background", "background.mp3")
            if os.path.exists(music_path):
                pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=512)
                pygame.mixer.music.load(music_path)
                print(f"Background music loaded: {music_path}")
            else:
                print(f"Background music file not found: {music_path}")
        except Exception as e:
            print(f"Failed to load background music: {e}")
    
    def start_background_music(self):
        """开始播放背景音乐"""
        try:
            if pygame.mixer.music.get_busy():
                return  # 音乐已经在播放
            
            pygame.mixer.music.play(-1)  # -1表示无限循环
            self.music_playing = True
            print("Background music started")
        except Exception as e:
            print(f"Failed to start background music: {e}")
    
    def stop_background_music(self):
        """停止背景音乐"""
        try:
            pygame.mixer.music.stop()
            self.music_playing = False
            print("Background music stopped")
        except Exception as e:
            print(f"Failed to stop background music: {e}")
    
    def _generate_card_categories(self):
        """动态生成卡牌分类选项，基于server/cards文件夹结构"""
        # 基础分类
        categories = ["All"]
        
        # 从card_registry中获取所有唯一的卡牌类型
        if hasattr(self.renderer, 'card_display') and hasattr(self.renderer.card_display, 'card_registry'):
            card_registry = self.renderer.card_display.card_registry
            unique_types = set()
            
            for card_data in card_registry.values():
                # 从description中提取子类型
                description = card_data.get("description", "")
                card_type = card_data.get("type", "Unknown")
                
                # 如果是Champion类型，尝试从description中提取子类型
                if card_type == "Champion":
                    if description.startswith("Warrior:"):
                        unique_types.add("Warrior")
                    elif description.startswith("Guard:"):
                        unique_types.add("Guard")
                    elif description.startswith("Mage:"):
                        unique_types.add("Mage")
                    elif description.startswith("Assassin:"):
                        unique_types.add("Assassin")
                    elif description.startswith("Rider:"):
                        unique_types.add("Rider")
                    else:
                        # 如果description里没有其他子类型标识，默认归类为Warrior
                        unique_types.add("Warrior")
                elif card_type == "Item":
                    unique_types.add("Item")
                elif card_type != "Summoner":  # 排除Summoner
                    unique_types.add(card_type)
            
            # 按特定顺序添加分类，不包含Summoner
            type_order = ["Warrior", "Guard", "Mage", "Assassin", "Rider", "Item"]
            for card_type in type_order:
                if card_type in unique_types:
                    categories.append(card_type)
            
            # 添加其他未列出的类型（除了Summoner）
            for card_type in sorted(unique_types):
                if card_type not in type_order and card_type != "Summoner":
                    categories.append(card_type)
        else:
            # 如果card_registry不可用，使用默认分类
            categories = ["All", "Warrior", "Guard", "Mage", "Assassin", "Rider", "Item"]
        
        return categories
    
    async def run(self):
        """运行游戏主循环"""
        while self.running:
            dt = self.clock.tick(60) / 1000.0  # 转换为秒
            
            # 处理事件
            await self.handle_events()
            
            # 更新动画
            self.animation_manager.update_animations(dt)
            
            # 更新消息计时器
            if self.message_timer > 0:
                self.message_timer -= dt
                if self.message_timer <= 0:
                    self.message_text = ""
                    self.message_color = None
            
            # 更新卡牌详情计时器
            if self.tooltip_timer > 0:
                self.tooltip_timer -= dt
                if self.tooltip_timer <= 0:
                    self.card_tooltip = None
            
            # 渲染
            self.render()
            
            # 等待下一帧
            await asyncio.sleep(0)
    
    async def handle_events(self):
        """处理事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
                if self.connected:
                    await self.client.disconnect()
                sys.exit()
            
            elif event.type == pygame.KEYDOWN:
                await self.handle_keydown(event)
            
            elif event.type == pygame.MOUSEBUTTONDOWN:
                await self.handle_mouse_down(event)
            
            elif event.type == pygame.MOUSEBUTTONUP:
                await self.handle_mouse_up(event)
            
            elif event.type == pygame.MOUSEMOTION:
                await self.handle_mouse_motion(event)
    
    async def handle_keydown(self, event):
        """处理按键事件"""
        # 检查是否按下了Ctrl+V (粘贴)
        ctrl_pressed = pygame.key.get_pressed()[pygame.K_LCTRL] or pygame.key.get_pressed()[pygame.K_RCTRL]
        
        if self.input_mode == "server_url":
            if event.key == pygame.K_RETURN:
                if self.server_url_input.strip():
                    self.server_url = self.server_url_input.strip()
                    self.input_mode = "room_manager"
                    # 获取房间列表
                    await self.refresh_rooms()
            elif event.key == pygame.K_BACKSPACE:
                self.server_url_input = self.server_url_input[:-1]
            elif event.key == pygame.K_v and ctrl_pressed:
                # 处理粘贴
                try:
                    import pyperclip
                    clipboard_text = pyperclip.paste()
                    if clipboard_text:
                        self.server_url_input += clipboard_text
                except ImportError:
                    # 如果没有pyperclip，尝试使用系统剪贴板
                    try:
                        import subprocess
                        if sys.platform == "darwin":  # macOS
                            result = subprocess.run(['pbpaste'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.server_url_input += result.stdout
                        elif sys.platform == "win32":  # Windows
                            result = subprocess.run(['powershell', '-command', 'Get-Clipboard'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.server_url_input += result.stdout
                        elif sys.platform == "linux":  # Linux
                            result = subprocess.run(['xclip', '-selection', 'clipboard', '-o'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.server_url_input += result.stdout
                    except:
                        pass  # 如果都失败了，就忽略
            else:
                self.server_url_input += event.unicode
        
        elif self.input_mode == "room_manager":
            # 房间管理界面的键盘输入处理（用于创建房间输入框）
            if event.key == pygame.K_BACKSPACE:
                self.create_room_input = self.create_room_input[:-1]
            elif event.key == pygame.K_v and ctrl_pressed:
                # 处理粘贴
                try:
                    import pyperclip
                    clipboard_text = pyperclip.paste()
                    if clipboard_text:
                        self.create_room_input += clipboard_text
                except ImportError:
                    # 如果没有pyperclip，尝试使用系统剪贴板
                    try:
                        import subprocess
                        if sys.platform == "darwin":  # macOS
                            result = subprocess.run(['pbpaste'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.create_room_input += result.stdout
                        elif sys.platform == "win32":  # Windows
                            result = subprocess.run(['powershell', '-command', 'Get-Clipboard'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.create_room_input += result.stdout
                        elif sys.platform == "linux":  # Linux
                            result = subprocess.run(['xclip', '-selection', 'clipboard', '-o'], capture_output=True, text=True)
                            if result.returncode == 0:
                                self.create_room_input += result.stdout
                    except:
                        pass  # 如果都失败了，就忽略
            else:
                self.create_room_input += event.unicode
        
        elif self.input_mode == "custom_deck_editor":
            # 自定义卡组编辑器的键盘输入处理
            if self.card_count_input_active:
                # 数量输入框激活
                if event.key == pygame.K_RETURN:
                    # 确认输入数量
                    try:
                        count = int(self.card_count_input)
                        if count > 0 and self.selected_card_for_count:
                            card_id = self.selected_card_for_count
                            current_total = sum(self.custom_deck_cards.values())
                            if current_total - self.custom_deck_cards.get(card_id, 0) + count <= 20:
                                self.custom_deck_cards[card_id] = count
                            else:
                                self.show_message("Deck total cannot exceed 20 cards", "red")
                        self.card_count_input = ""
                        self.card_count_input_active = False
                        self.selected_card_for_count = None
                    except ValueError:
                        self.show_message("Please enter a valid number", "red")
                elif event.key == pygame.K_BACKSPACE:
                    self.card_count_input = self.card_count_input[:-1]
                elif event.key == pygame.K_v and ctrl_pressed:
                    # 处理粘贴
                    try:
                        import pyperclip
                        clipboard_text = pyperclip.paste()
                        if clipboard_text:
                            self.card_count_input += clipboard_text
                    except ImportError:
                        pass
                elif event.unicode.isdigit():
                    self.card_count_input += event.unicode
            else:
                # 卡组名称或描述输入
                if event.key == pygame.K_BACKSPACE:
                    if self.name_input_active:
                        self.custom_deck_name = self.custom_deck_name[:-1]
                    elif self.desc_input_active:
                        self.custom_deck_description = self.custom_deck_description[:-1]
                elif event.key == pygame.K_v and ctrl_pressed:
                    # 处理粘贴
                    try:
                        import pyperclip
                        clipboard_text = pyperclip.paste()
                        if clipboard_text:
                            if self.name_input_active:
                                self.custom_deck_name += clipboard_text
                            elif self.desc_input_active:
                                self.custom_deck_description += clipboard_text
                    except ImportError:
                        pass
                else:
                    if self.name_input_active:
                        self.custom_deck_name += event.unicode
                    elif self.desc_input_active:
                        self.custom_deck_description += event.unicode
    
    async def handle_mouse_down(self, event):
        """处理鼠标按下事件"""
        if event.button == 1:  # 左键
            # 缩放鼠标位置到虚拟分辨率
            scaled_pos = self.renderer.scale_mouse_pos(event.pos)
            if self.input_mode == "playing":
                await self.handle_game_click(scaled_pos)
            elif self.input_mode == "server_url":
                # 检查确认按钮
                confirm_rect = pygame.Rect(self.renderer.design_width // 2 - 60, 350, 120, 40)
                if confirm_rect.collidepoint(scaled_pos):
                    if self.server_url_input.strip():
                        self.server_url = self.server_url_input.strip()
                        self.input_mode = "room_manager"
                        # 获取房间列表
                        await self.refresh_rooms()
                else:
                    # 检查输入框（使用居中坐标）
                    input_width = 400
                    input_height = 40
                    input_x = self.renderer.design_width // 2 - input_width // 2
                    input_rect = pygame.Rect(input_x, 300, input_width, input_height)
                    if input_rect.collidepoint(scaled_pos):
                        pass  # 输入框点击处理
            elif self.input_mode == "room_manager":
                # 房间管理界面的点击处理
                await self.handle_room_manager_click(scaled_pos)
            elif self.input_mode == "custom_deck_editor":
                # 自定义卡组编辑器的点击处理
                await self.handle_custom_deck_editor_click(scaled_pos)
            elif self.input_mode == "game_over":
                # 游戏结束界面的点击处理
                await self.handle_game_over_click(scaled_pos)
        
        elif event.button == 3:  # 右键
            scaled_pos = self.renderer.scale_mouse_pos(event.pos)
            if self.input_mode == "server_url":
                # 右键粘贴到服务器地址输入框
                input_width = 400
                input_height = 40
                input_x = self.renderer.design_width // 2 - input_width // 2
                input_rect = pygame.Rect(input_x, 300, input_width, input_height)
                if input_rect.collidepoint(scaled_pos):
                    pasted = None
                    try:
                        import pyperclip
                        pasted = pyperclip.paste()
                    except Exception:
                        try:
                            import subprocess, sys
                            if sys.platform == "darwin":
                                result = subprocess.run(['pbpaste'], capture_output=True, text=True)
                                if result.returncode == 0:
                                    pasted = result.stdout
                            elif sys.platform == "win32":
                                result = subprocess.run(['powershell', '-command', 'Get-Clipboard'], capture_output=True, text=True)
                                if result.returncode == 0:
                                    pasted = result.stdout
                            elif sys.platform == "linux":
                                result = subprocess.run(['xclip', '-selection', 'clipboard', '-o'], capture_output=True, text=True)
                                if result.returncode == 0:
                                    pasted = result.stdout
                        except Exception:
                            pasted = None
                    if pasted:
                        self.server_url_input = pasted.strip()
                return
            elif self.input_mode == "playing":
                # 右键显示卡牌详情（游戏阶段）
                self.show_card_tooltip(scaled_pos)
    
    async def handle_mouse_up(self, event):
        """处理鼠标释放事件"""
        if event.button == 1:  # 左键
            if self.input_mode == "playing":
                scaled_pos = self.renderer.scale_mouse_pos(event.pos)
                await self.handle_game_release(scaled_pos)
    
    async def handle_mouse_motion(self, event):
        """处理鼠标移动事件"""
        if self.input_mode == "playing":
            # 检查是否在拖拽
            pass
    
    async def refresh_rooms(self):
        """刷新房间列表"""
        try:
            rooms_data = await self.client.fetch_rooms(self.server_url)
            if rooms_data and "rooms" in rooms_data:
                self.rooms_list = rooms_data["rooms"]
            else:
                self.rooms_list = []
        except Exception as e:
            print(f"Error refreshing rooms: {e}")
            self.rooms_list = []
    
    async def handle_room_manager_click(self, pos):
        """处理房间管理界面的点击"""
        # 左侧区域（约40%宽度）
        left_width = int(self.renderer.design_width * 0.4)
        
        # 右侧区域（约60%宽度）
        right_start = left_width
        
        # 检查是否点击了左侧区域
        if pos[0] < left_width:
            # 检查刷新按钮
            refresh_button_rect = pygame.Rect(20, self.renderer.design_height - 60, 100, 40)
            if refresh_button_rect.collidepoint(pos):
                await self.refresh_rooms()
                return
            
            # 检查房间列表项
            room_list_start_y = 100
            room_item_height = 30
            for i, room in enumerate(self.rooms_list):
                room_rect = pygame.Rect(20, room_list_start_y + i * room_item_height, left_width - 40, room_item_height)
                if room_rect.collidepoint(pos):
                    self.selected_room_id = room["room_id"]
                    return
        
        # 检查是否点击了右侧区域
        elif pos[0] >= right_start:
            # 创建房间区域
            create_section_y = 200
            create_input_rect = pygame.Rect(right_start + 20, create_section_y + 50, 300, 40)
            create_button_rect = pygame.Rect(right_start + 20, create_section_y + 100, 120, 40)
            
            if create_input_rect.collidepoint(pos):
                # 点击了创建房间输入框
                pass
            elif create_button_rect.collidepoint(pos):
                # 点击了创建房间按钮
                if self.create_room_input.strip():
                    self.room_id = self.create_room_input.strip()
                    self.player_id = f"player_{pygame.time.get_ticks()}"
                    await self.connect_to_server()
            
            # 加入房间区域
            join_section_y = 350
            join_button_rect = pygame.Rect(right_start + 20, join_section_y + 100, 120, 40)
            
            if join_button_rect.collidepoint(pos):
                # 点击了加入房间按钮
                if self.selected_room_id:
                    self.room_id = self.selected_room_id
                    self.player_id = f"player_{pygame.time.get_ticks()}"
                    await self.connect_to_server()
            
            # 自定义卡组区域
            custom_deck_section_y = 500
            custom_deck_button_rect = pygame.Rect(right_start + 20, custom_deck_section_y + 50, 150, 40)
            
            if custom_deck_button_rect.collidepoint(pos):
                # 点击了自定义卡组按钮
                self.input_mode = "custom_deck_editor"
                # 重置编辑器状态
                self.custom_deck_name = ""
                self.custom_deck_description = ""
                self.custom_deck_cards = {}
                self.selected_card_for_count = None
                self.card_count_input = ""
                self.card_count_input_active = False
    
    async def handle_custom_deck_editor_click(self, pos):
        """处理自定义卡组编辑器的点击"""
        # 检查右上角"读取现有卡组"按钮点击
        load_deck_button_rect = pygame.Rect(self.renderer.design_width - 200, 20, 180, 40)
        if load_deck_button_rect.collidepoint(pos):
            # 加载卡组列表并显示弹出层
            self.load_custom_decks()
            self.show_deck_list = True
            return
        
        # 检查卡牌网格点击
        card_registry = self.renderer.card_display.card_registry
        card_ids = list(card_registry.keys())
        
        # 按分类过滤卡牌（与渲染逻辑保持一致）
        if self.card_category != "All":
            filtered_card_ids = []
            for card_id in card_ids:
                card_data = card_registry[card_id]
                description = card_data.get("description", "")
                card_type = card_data.get("type", "Unknown")
                
                # 根据description判断子类型
                if card_type == "Champion":
                    if self.card_category == "Warrior" and (description.startswith("Warrior:") or not any(description.startswith(prefix) for prefix in ["Guard:", "Mage:", "Assassin:", "Rider:"])):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Guard" and description.startswith("Guard:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Mage" and description.startswith("Mage:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Assassin" and description.startswith("Assassin:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Rider" and description.startswith("Rider:"):
                        filtered_card_ids.append(card_id)
                elif card_type == "Item" and self.card_category == "Item":
                    filtered_card_ids.append(card_id)
                elif card_type == self.card_category:
                    filtered_card_ids.append(card_id)
            
            card_ids = filtered_card_ids
        else:
            # All分类中排除Summoner类型的卡牌
            card_ids = [card_id for card_id in card_ids 
                       if card_registry[card_id].get("type") != "Summoner"]
        
        # 计算卡牌网格布局
        cards_per_row = 8
        card_width = self.renderer.card_display.card_width
        card_height = self.renderer.card_display.card_height
        card_spacing = 10
        
        grid_start_x = 50
        grid_start_y = 200
        grid_width = cards_per_row * (card_width + card_spacing) - card_spacing
        
        for i, card_id in enumerate(card_ids):
            row = i // cards_per_row
            col = i % cards_per_row
            
            card_x = grid_start_x + col * (card_width + card_spacing)
            card_y = grid_start_y + row * (card_height + card_spacing)
            
            card_rect = pygame.Rect(card_x, card_y, card_width, card_height)
            
            if card_rect.collidepoint(pos):
                # 点击了卡牌，准备设置数量
                self.selected_card_for_count = card_id
                self.card_count_input_active = True
                self.card_count_input = str(self.custom_deck_cards.get(card_id, 1))
                return
        
        # 检查已选卡牌列表点击
        selected_cards_start_x = grid_start_x + grid_width + 50
        selected_cards_start_y = grid_start_y
        selected_card_height = 30
        
        for i, (card_id, count) in enumerate(self.custom_deck_cards.items()):
            card_y = selected_cards_start_y + i * (selected_card_height + 5)
            card_rect = pygame.Rect(selected_cards_start_x, card_y, 200, selected_card_height)
            
            if card_rect.collidepoint(pos):
                # 点击了已选卡牌，可以修改数量或删除
                self.selected_card_for_count = card_id
                self.card_count_input_active = True
                self.card_count_input = str(count)
                return
        
        # 检查输入框点击
        # 名称输入框
        name_input_rect = pygame.Rect(200, 100, 300, 30)
        if name_input_rect.collidepoint(pos):
            self.name_input_active = True
            self.desc_input_active = False
            self.card_count_input_active = False
            return
        
        # 描述输入框
        desc_input_rect = pygame.Rect(200, 140, 400, 30)
        if desc_input_rect.collidepoint(pos):
            self.name_input_active = False
            self.desc_input_active = True
            self.card_count_input_active = False
            return
        
        # 分类下拉菜单
        category_rect = pygame.Rect(120, 180, 120, 30)
        if category_rect.collidepoint(pos):
            # 切换到下一个分类
            current_index = self.card_category_options.index(self.card_category)
            next_index = (current_index + 1) % len(self.card_category_options)
            self.card_category = self.card_category_options[next_index]
            return
        
        # 检查按钮点击 - 右下角控制区域
        control_start_x = self.renderer.design_width - 300
        control_start_y = self.renderer.design_height - 200
        
        # 保存按钮
        save_button_rect = pygame.Rect(control_start_x, control_start_y + 80, 80, 40)
        if save_button_rect.collidepoint(pos):
            await self.save_custom_deck()
            return
        
        # 取消按钮
        cancel_button_rect = pygame.Rect(control_start_x + 100, control_start_y + 80, 80, 40)
        if cancel_button_rect.collidepoint(pos):
            self.input_mode = "room_manager"
            # 重置编辑器状态
            self.custom_deck_name = ""
            self.custom_deck_description = ""
            self.custom_deck_cards = {}
            self.selected_card_for_count = None
            self.card_count_input = ""
            self.card_count_input_active = False
            self.name_input_active = False
            self.desc_input_active = False
            self.editing_deck_filename = ""  # 重置编辑状态
            self.show_deck_list = False  # 关闭卡组列表
            return
        
        # 数量输入框
        count_input_rect = pygame.Rect(control_start_x + 60, control_start_y + 30, 60, 30)
        if count_input_rect.collidepoint(pos):
            self.card_count_input_active = True
            self.name_input_active = False
            self.desc_input_active = False
            return
        
        # 添加按钮
        add_button_rect = pygame.Rect(control_start_x + 130, control_start_y + 30, 50, 30)
        if add_button_rect.collidepoint(pos) and self.selected_card_for_count:
            try:
                count = int(self.card_count_input)
                if count > 0:
                    card_id = self.selected_card_for_count
                    current_total = sum(self.custom_deck_cards.values())
                    if current_total - self.custom_deck_cards.get(card_id, 0) + count <= 20:
                        self.custom_deck_cards[card_id] = count
                    else:
                        self.show_message("Deck total cannot exceed 20 cards", "red")
                self.card_count_input = ""
                self.card_count_input_active = False
                self.selected_card_for_count = None
            except ValueError:
                self.show_message("Please enter a valid number", "red")
            return
        
        # 删除按钮
        delete_button_rect = pygame.Rect(control_start_x + 190, control_start_y + 30, 50, 30)
        if delete_button_rect.collidepoint(pos) and self.selected_card_for_count:
            card_id = self.selected_card_for_count
            if card_id in self.custom_deck_cards:
                del self.custom_deck_cards[card_id]
            self.card_count_input = ""
            self.card_count_input_active = False
            self.selected_card_for_count = None
            return
        
        # 检查卡组列表弹出层的点击
        if self.show_deck_list:
            await self.handle_deck_list_click(pos)
            return

    async def handle_deck_list_click(self, pos):
        """处理卡组列表弹出层的点击"""
        # 弹出层窗口参数
        window_width = 600
        window_height = 500
        window_x = (self.renderer.design_width - window_width) // 2
        window_y = (self.renderer.design_height - window_height) // 2
        
        # 检查关闭按钮
        close_button_rect = pygame.Rect(window_x + window_width - 40, window_y + 10, 30, 30)
        if close_button_rect.collidepoint(pos):
            self.show_deck_list = False
            return
        
        # 检查卡组列表项
        list_start_y = window_y + 70
        item_height = 60
        max_items = 6
        
        for i, deck in enumerate(self.custom_decks_list[:max_items]):
            item_y = list_start_y + i * item_height
            item_rect = pygame.Rect(window_x + 20, item_y, window_width - 40, item_height - 10)
            
            # 检查加载按钮
            load_button_rect = pygame.Rect(item_rect.right - 120, item_rect.y + 10, 50, 30)
            if load_button_rect.collidepoint(pos):
                self.load_deck_into_editor(deck['filepath'])
                return
            
            # 检查删除按钮
            delete_button_rect = pygame.Rect(item_rect.right - 60, item_rect.y + 10, 50, 30)
            if delete_button_rect.collidepoint(pos):
                # 直接删除
                self.delete_custom_deck(deck['filepath'])
                return

    async def handle_game_over_click(self, pos):
        """处理游戏结束界面的点击"""
        # 返回房间选择按钮
        return_button_rect = pygame.Rect(self.renderer.design_width // 2 - 100, 400, 200, 50)
        
        if return_button_rect.collidepoint(pos):
            # 点击了返回按钮，回到房间管理界面
            self.input_mode = "room_manager"
            self.game_over_result = None
            # 刷新房间列表
            await self.refresh_rooms()
    
    async def save_custom_deck(self):
        """保存自定义卡组"""
        # 验证卡组名称和描述
        if not self.custom_deck_name.strip():
            self.show_message("Please enter deck name", "red")
            return
        
        if not self.custom_deck_description.strip():
            self.show_message("Please enter deck description", "red")
            return
        
        # 验证卡牌总数
        total_cards = sum(self.custom_deck_cards.values())
        if total_cards != 20:
            self.show_message(f"Deck must contain exactly 20 cards, currently has {total_cards}", "red")
            return
        
        # 创建卡组数据
        deck_data = {
            "title": self.custom_deck_name.strip(),
            "description": self.custom_deck_description.strip(),
            "cards": []
        }
        
        for card_id, count in self.custom_deck_cards.items():
            deck_data["cards"].append({
                "card_id": card_id,
                "count": count
            })
        
        # 保存到文件
        try:
            import os
            import json
            import re
            
            # 创建owndeck目录
            owndeck_dir = os.path.join(os.path.dirname(__file__), "owndeck")
            os.makedirs(owndeck_dir, exist_ok=True)
            
            # 确定文件名和路径
            if self.editing_deck_filename:
                # 覆盖现有文件
                filepath = os.path.join(owndeck_dir, self.editing_deck_filename)
            else:
                # 创建新文件
                filename = re.sub(r'[^\w\-_]', '_', self.custom_deck_name.strip())
                filename = f"{filename}.json"
                filepath = os.path.join(owndeck_dir, filename)
            
            with open(filepath, "w", encoding="utf-8") as f:
                json.dump(deck_data, f, ensure_ascii=False, indent=2)
            
            action = "updated" if self.editing_deck_filename else "saved"
            self.show_message(f"Deck '{self.custom_deck_name}' {action} successfully", "green")
            
            # 重置编辑状态
            self.editing_deck_filename = ""
            
            # 返回房间管理界面
            self.input_mode = "room_manager"
            
        except Exception as e:
            self.show_message(f"保存失败: {e}", "red")
    
    def load_custom_decks(self):
        """从owndeck目录加载所有自定义卡组"""
        import os
        import json
        
        self.custom_decks_list = []
        owndeck_dir = os.path.join(os.path.dirname(__file__), "owndeck")
        
        if not os.path.exists(owndeck_dir):
            return
        
        try:
            for filename in os.listdir(owndeck_dir):
                if filename.endswith('.json'):
                    filepath = os.path.join(owndeck_dir, filename)
                    try:
                        with open(filepath, 'r', encoding='utf-8') as f:
                            deck_data = json.load(f)
                        
                        # 验证文件格式
                        if 'title' in deck_data and 'description' in deck_data:
                            self.custom_decks_list.append({
                                'filename': filename,
                                'filepath': filepath,
                                'title': deck_data.get('title', 'Unknown'),
                                'description': deck_data.get('description', ''),
                                'card_count': len(deck_data.get('cards', []))
                            })
                    except (json.JSONDecodeError, KeyError) as e:
                        print(f"Error loading deck {filename}: {e}")
                        continue
        except Exception as e:
            print(f"Error scanning owndeck directory: {e}")
    
    def load_deck_into_editor(self, filepath):
        """将指定卡组加载到编辑器中"""
        import json
        
        try:
            with open(filepath, 'r', encoding='utf-8') as f:
                deck_data = json.load(f)
            
            # 加载卡组信息
            self.custom_deck_name = deck_data.get('title', '')
            self.custom_deck_description = deck_data.get('description', '')
            
            # 加载卡牌
            self.custom_deck_cards = {}
            for card_info in deck_data.get('cards', []):
                card_id = card_info.get('card_id')
                count = card_info.get('count', 1)
                if card_id:
                    self.custom_deck_cards[card_id] = count
            
            # 记录正在编辑的文件名
            import os
            self.editing_deck_filename = os.path.basename(filepath)
            
            # 关闭卡组列表
            self.show_deck_list = False
            
            self.show_message(f"Loaded deck: {self.custom_deck_name}", "green")
            
        except Exception as e:
            self.show_message(f"Failed to load deck: {e}", "red")
    
    def delete_custom_deck(self, filepath):
        """删除指定的卡组文件"""
        import os
        
        try:
            if os.path.exists(filepath):
                os.remove(filepath)
                self.show_message("Deck deleted successfully", "green")
                # 重新加载卡组列表
                self.load_custom_decks()
            else:
                self.show_message("Deck file not found", "red")
        except Exception as e:
            self.show_message(f"Failed to delete deck: {e}", "red")
    
    async def connect_to_server(self):
        """连接到服务器"""
        try:
            # 验证服务器地址格式
            if not self.server_url.startswith(('ws://', 'wss://')):
                self.show_message("Invalid server URL format. Please use format: ws://localhost:8001", "red")
                return
            
            print(f"Attempting to connect to: {self.server_url}")
            success = await self.client.connect(self.server_url, self.room_id, self.player_id)
            if success:
                self.connected = True
                self.input_mode = "playing"
                print(f"Connected to server: {self.server_url}")
            else:
                print("Connection failed")
                # 连接失败时保持在房间管理界面
                self.input_mode = "room_manager"
        except Exception as e:
            print(f"Connection error: {e}")
            self.show_message(f"Connection error: {e}", "red")
            # 连接失败时保持在房间管理界面
            self.input_mode = "room_manager"
    
    async def handle_game_click(self, pos):
        """处理游戏中的点击"""
        game_state = self.client.get_game_state()
        if not game_state:
            return
        
        # 处理Flag选择
        if self.flag_choice_required:
            # 检查是否点击了选择按钮
            choice_width = 400
            choice_height = 200
            choice_x = self.renderer.design_width // 2 - choice_width // 2
            choice_y = self.renderer.design_height // 2 - choice_height // 2
            
            button_width = 300
            button_height = 40
            button_spacing = 60
            
            for i, choice in enumerate(self.flag_choices):
                button_x = choice_x + (choice_width - button_width) // 2
                button_y = choice_y + 60 + i * button_spacing
                button_rect = pygame.Rect(button_x, button_y, button_width, button_height)
                
                if button_rect.collidepoint(pos):
                    self.handle_flag_choice(choice.get("id", str(i)))
                    return
        
        # 检查是否在卡组选择阶段
        if self.client.is_deck_selection_phase():
            await self.handle_deck_selection_click(pos, game_state)
        # 检查是否在换牌阶段
        elif self.client.is_mulligan_phase():
            await self.handle_mulligan_click(pos, game_state)
        else:
            await self.handle_playing_click(pos, game_state)
    
    async def handle_deck_selection_click(self, pos, game_state):
        """处理卡组选择阶段的点击"""
        # 检查玩家是否已选择卡组
        deck_selection_completed = game_state.get("deck_selection_completed", False)
        
        # 如果已选择，忽略所有点击
        if deck_selection_completed:
            return
        
        # 获取可用卡组
        available_decks = self.client.get_available_decks()
        
        # 卡组按钮位置（垂直排列）
        button_width = 400
        button_height = 80
        start_y = 150
        button_spacing = 20
        
        for i, deck in enumerate(available_decks):
            button_x = self.renderer.design_width // 2 - button_width // 2
            button_y = start_y + i * (button_height + button_spacing)
            button_rect = pygame.Rect(button_x, button_y, button_width, button_height)
            
            if button_rect.collidepoint(pos):
                # 选择这个卡组
                self.selected_deck = deck.get("name")
                await self.client.send_select_deck(self.selected_deck)
                return
    
    async def handle_mulligan_click(self, pos, game_state):
        """处理换牌阶段的点击"""
        # 检查玩家是否已完成换牌
        mulligan_completed = game_state.get("mulligan_completed", False)
        
        # 如果已完成换牌，忽略所有点击
        if mulligan_completed:
            return
        
        mulligan_cards = self.client.get_mulligan_cards()  # 返回card_id字符串列表
        
        # 检查是否点击了卡牌（使用居中坐标）
        card_width = self.renderer.card_width
        card_spacing = self.renderer.card_spacing
        total_width = len(mulligan_cards) * card_width + (len(mulligan_cards) - 1) * card_spacing
        start_x = self.renderer.design_width // 2 - total_width // 2
        
        for i, card_id in enumerate(mulligan_cards):
            card_x = start_x + i * (card_width + card_spacing)
            card_y = 100
            card_rect = pygame.Rect(card_x, card_y, card_width, self.renderer.card_height)
            
            if card_rect.collidepoint(pos):
                # 使用(索引, card_id)元组来追踪，避免同种卡牌的混淆
                card_tuple = (i, card_id)
                if card_tuple in self.selected_cards:
                    self.selected_cards.remove(card_tuple)
                else:
                    if len(self.selected_cards) < 4:
                        self.selected_cards.append(card_tuple)
                return
        
        # 检查确认按钮
        confirm_rect = pygame.Rect(self.renderer.design_width // 2 - 60, self.renderer.design_height - 100, 120, 40)
        if confirm_rect.collidepoint(pos):
            if len(self.selected_cards) == 4:
                # 提取card_id（按选择的索引顺序）
                selected_card_ids = [card_id for _, card_id in self.selected_cards]
                await self.client.send_mulligan(selected_card_ids)
                self.selected_cards = []
                return
    
    def _card_needs_target(self, card):
        """判断卡牌是否需要目标"""
        # 所有Guard类型的卡牌都需要选择目标
        card_id = card.get("card_id", "")
        guard_cards = ["test_guard", "zhen_ji", "sun_ce", "zhou_yu", "zhang_liang", 
                      "hua_mulan", "liu_bei", "lu_ban", "diao_chan", "li_shuwen", "liu_bang"]
        if card_id in guard_cards:
            return True
        if card_id == "jing_ke":
            return True
        if card_id == "xi_shi":
            return True
        if card.get("type") == "Item" and card.get("target_required"):
            return True
        return False
    
    def _get_valid_targets_for_card(self, card):
        """获取卡牌的有效目标"""
        valid_targets = []
        card_id = card.get("card_id", "")
        
        # 检查是否为Guard卡
        guard_cards = ["test_guard", "zhen_ji", "sun_ce", "zhou_yu", "zhang_liang", 
                      "hua_mulan", "liu_bei", "lu_ban", "diao_chan", "li_shuwen", "liu_bang"]
        if card_id in guard_cards:
            # 所有Guard可以守卫己方召唤师和己方场上单位（但不能守卫其他Guard）
            valid_targets.append({"type": "summoner", "id": f"{self.player_id}_summoner"})
            my_battlefield = self.client.get_my_battlefield()
            for champion in my_battlefield:
                if champion:
                    # 排除其他Guard卡牌
                    champion_id = champion.get("card_id", "")
                    if champion_id not in guard_cards:
                        valid_targets.append({
                            "type": "champion",
                            "id": champion.get("instance_id")
                        })
        
        elif card_id == "jing_ke":
            # JingKe只能对敌方场上单位造成伤害，不能选择召唤师
            game_state = self.client.get_game_state()
            if game_state:
                # 只添加敌方场上单位（排除隐身的）
                opponent_battlefield = self.client.get_opponent_battlefield()
                for champion in opponent_battlefield:
                    if champion and not champion.get("is_hidden", False):
                        valid_targets.append({
                            "type": "champion",
                            "id": champion.get("instance_id")
                        })
        
        elif card_id == "xi_shi":
            # Xi Shi可以攻击敌方召唤师和敌方场上单位
            game_state = self.client.get_game_state()
            if game_state:
                opponent_id = self.client.get_opponent_id()
                if opponent_id:
                    # 添加敌方召唤师
                    valid_targets.append({"type": "summoner", "id": f"{opponent_id}_summoner"})
                    # 添加敌方场上单位（排除隐身的）
                    opponent_battlefield = self.client.get_opponent_battlefield()
                    for champion in opponent_battlefield:
                        if champion and not champion.get("is_hidden", False):
                            valid_targets.append({
                                "type": "champion",
                                "id": champion.get("instance_id") or champion.get("card_id")
                            })
        
        elif card.get("type") == "Item" and card.get("target_required"):
            # 根据道具类型选择有效目标
            if card_id == "knife":
                # Knife只能选择敌方champion（不能选择召唤师）
                game_state = self.client.get_game_state()
                if game_state:
                    opponent_battlefield = self.client.get_opponent_battlefield()
                    for champion in opponent_battlefield:
                        if champion and not champion.get("is_hidden", False):
                            valid_targets.append({
                                "type": "champion",
                                "id": champion.get("instance_id") or champion.get("card_id")
                            })
            # 攻击型道具：Sword, Fan等可以攻击敌方召唤师和敌方单位
            elif card_id in ["fan", "sword"]:
                # 可以攻击敌方召唤师和敌方场上单位
                game_state = self.client.get_game_state()
                if game_state:
                    opponent_id = self.client.get_opponent_id()
                    if opponent_id:
                        # 添加敌方召唤师
                        valid_targets.append({"type": "summoner", "id": f"{opponent_id}_summoner"})
                        # 添加敌方场上单位（排除隐身的）
                        opponent_battlefield = self.client.get_opponent_battlefield()
                        for champion in opponent_battlefield:
                            if champion and not champion.get("is_hidden", False):
                                valid_targets.append({
                                    "type": "champion",
                                    "id": champion.get("instance_id")
                                })
            else:
                # 治疗型道具：HealPotion等可以治疗己方单位
                valid_targets.append({"type": "summoner", "id": f"{self.player_id}_summoner"})
                my_battlefield = self.client.get_my_battlefield()
                for champion in my_battlefield:
                    if champion:
                        valid_targets.append({
                            "type": "champion",
                            "id": champion.get("instance_id")
                        })
        
        return valid_targets
    
    def _get_valid_attack_targets(self):
        """获取可攻击的目标"""
        valid_targets = []
        
        # 获取对手ID
        game_state = self.client.get_game_state()
        if not game_state:
            return valid_targets
        
        players = game_state.get("players", {})
        opponent_id = None
        for pid in players.keys():
            if pid != self.player_id:
                opponent_id = pid
                break
        
        if not opponent_id:
            return valid_targets
        
        # 获取对手场上单位
        opponent_battlefield = self.client.get_opponent_battlefield()
        
        # 找出所有被守卫的目标
        guarded_targets = set()
        for champion in opponent_battlefield:
            if champion and champion.get("guarding_target_id"):
                guarded_targets.add(champion.get("guarding_target_id"))
        
        # 对手召唤师（如果没有被守卫）
        summoner_id = f"{opponent_id}_summoner"
        if summoner_id not in guarded_targets:
            valid_targets.append({"type": "summoner", "id": summoner_id})
        
        # 对手场上单位（排除隐身的Assassin和被守卫的单位）
        for champion in opponent_battlefield:
            if champion and not champion.get("is_hidden", False):
                champion_id = champion.get("instance_id") or champion.get("card_id")
                # 排除被守卫的单位
                if champion_id not in guarded_targets:
                    valid_targets.append({
                        "type": "champion",
                        "id": champion_id
                    })
        
        return valid_targets
    
    def _get_valid_effect_targets(self):
        """获取有效的效果目标（敌方单位）"""
        return self._get_valid_attack_targets()
    
    async def _execute_pending_action(self):
        """执行待处理的动作"""
        # 检查是否是我的回合
        if not self.client.is_my_turn():
            self.show_message("Not your turn!", "red")
            return
        
        if self.pending_action == "SUMMON":
            # 检查PP是否足够
            game_state = self.client.get_game_state()
            if game_state:
                my_data = game_state.get("players", {}).get(self.player_id, {})
                current_pp = my_data.get("current_pp", 0)
                card_cost = self.pending_card_data.get("cost", 0)
                
                if current_pp < card_cost:
                    self.show_message(f"Insufficient PP! Need {card_cost}, have {current_pp}", "red")
                    return
            
            # 查找空位置
            my_battlefield = self.client.get_my_battlefield()
            empty_position = None
            for i, champion in enumerate(my_battlefield):
                if champion is None:
                    empty_position = i
                    break
            
            if empty_position is None:
                self.show_message("Battlefield is full!", "red")
                return
            
            # 使用保存的位置
            position = self.pending_position if self.pending_position is not None else empty_position
            
            # 检查是否为Guard
            pending_card_id = self.pending_card_data.get("card_id", "")
            guard_cards = ["test_guard", "zhen_ji", "sun_ce", "zhou_yu", "zhang_liang", 
                          "hua_mulan", "liu_bei", "lu_ban", "diao_chan", "li_shuwen", "liu_bang"]
            if pending_card_id in guard_cards:
                # 所有Guard需要选择守卫目标
                await self.client.send_summon(
                    self.pending_card_data.get("card_id"),
                    position,
                    self.selected_target
                )
            elif self.pending_card_data.get("card_id") == "jing_ke":
                # JingKe需要选择目标
                await self.client.send_summon(
                    self.pending_card_data.get("card_id"),
                    position,
                    None,  # guard_target
                    self.selected_target  # effect_target
                )
            elif self.pending_card_data.get("card_id") == "xi_shi":
                # Xi Shi需要选择效果目标
                await self.client.send_summon(
                    self.pending_card_data.get("card_id"),
                    position,
                    None,  # guard_target
                    self.selected_target  # effect_target
                )
            else:
                await self.client.send_summon(
                    self.pending_card_data.get("card_id"),
                    position
                )
        
        elif self.pending_action == "USE_ITEM":
            # 检查PP是否足够
            game_state = self.client.get_game_state()
            if game_state:
                my_data = game_state.get("players", {}).get(self.player_id, {})
                current_pp = my_data.get("current_pp", 0)
                card_cost = self.pending_card_data.get("cost", 0)
                
                if current_pp < card_cost:
                    self.show_message(f"Insufficient PP! Need {card_cost}, have {current_pp}", "red")
                    return
            
            if self.selected_target:
                await self.client.send_use_item(
                    self.pending_card_data.get("card_id"),
                    self.selected_target
                )
            else:
                await self.client.send_use_item(self.pending_card_data.get("card_id"))
        
        elif self.pending_action == "ATTACK":
            await self.client.send_attack(self.pending_card, self.selected_target)
    
    def _reset_interaction_state(self):
        """重置交互状态"""
        self.interaction_state = "IDLE"
        self.pending_card = None
        self.pending_card_data = None
        self.pending_action = None
        self.selected_target = None
        self.valid_targets = []
    
    def show_message(self, text: str, color_name: str = "red"):
        """显示游戏消息提示"""
        self.message_text = text
        self.message_color = self.renderer.colors.get(color_name, self.renderer.colors['red'])
        self.message_timer = self.message_duration
        
        # 如果是房间已满的错误，确保保持在房间管理界面
        if "Room is full" in text and self.input_mode != "room_manager":
            self.input_mode = "room_manager"
            self.connected = False
    
    def handle_game_over(self, result: Dict[str, Any]):
        """处理游戏结束"""
        self.game_over_result = result
        self.input_mode = "game_over"
        self.connected = False
        
        # 停止背景音乐
        self.stop_background_music()
    
    def handle_animation(self, animation_type: str, data: Dict[str, Any]):
        """处理动画触发"""
        if animation_type == "summon":
            self._handle_summon_animation(data)
        elif animation_type == "use_item":
            self._handle_use_item_animation(data)
        elif animation_type == "attack":
            self._handle_attack_animation(data)
    
    def _handle_summon_animation(self, data: Dict[str, Any]):
        """处理召唤动画"""
        # 获取卡牌信息
        card_id = data.get('card_id', '')
        position = data.get('position', 0)
        hand_index = data.get('hand_index', -1)  # 从服务器获取手牌索引
        player_id = data.get('player_id', '')  # 获取操作玩家ID
        
        # 计算手牌位置
        game_state = self.client.get_game_state()
        if not game_state:
            return
        
        # 判断是己方还是对手
        is_my_animation = (player_id == self.player_id)
        
        if is_my_animation:
            # 己方的动画：从我的手牌飞出
            my_hand = self.client.get_my_hand()
            if not my_hand:
                return
            
            # 使用实际的手牌索引计算起始位置
            hand_y = self.renderer.design_height - self.renderer.card_height - 10
            total_width = len(my_hand) * self.renderer.card_width + (len(my_hand) - 1) * self.renderer.card_spacing
            start_x = self.renderer.design_width // 2 - total_width // 2
            
            if hand_index >= 0 and hand_index < len(my_hand):
                hand_start_x = start_x + hand_index * (self.renderer.card_width + self.renderer.card_spacing)
            else:
                hand_start_x = self.renderer.design_width // 2
            hand_start_y = hand_y
        else:
            # 对手的动画：从对手的手牌区域飞出
            hand_start_x = self.renderer.design_width // 2
            hand_start_y = 100  # 顶部手牌区域
        
        # 计算场地目标位置
        center_line = self.renderer.design_height // 2
        
        # 根据玩家判断目标场地位置
        if is_my_animation:
            battlefield_y = center_line + 100 - 150  # 我的场地上移150px
            battlefield = self.client.get_my_battlefield()
        else:
            battlefield_y = center_line - 100 - self.renderer.card_height  # 对手场地
            battlefield = self.client.get_opponent_battlefield()
        
        # 计算场地位置（动态居中）
        champions_count = sum(1 for c in battlefield if c is not None)
        
        if champions_count > 0:
            total_width = champions_count * self.renderer.card_width + (champions_count - 1) * self.renderer.card_spacing
            battlefield_start_x = self.renderer.design_width // 2 - total_width // 2
        else:
            battlefield_start_x = self.renderer.design_width // 2
        
        battlefield_target_x = battlefield_start_x + position * (self.renderer.card_width + self.renderer.card_spacing)
        battlefield_target_y = battlefield_y
        
        # 获取卡牌数据
        card_data = self._get_card_data(card_id)
        
        # 创建召唤动画
        animation_id = self.animation_manager.add_card_summon_animation(
            (hand_start_x, hand_start_y),
            (battlefield_target_x, battlefield_target_y)
        )
        
        # 添加卡牌数据到动画
        if animation_id is not None:
            for animation in self.animation_manager.animations:
                if animation['id'] == animation_id:
                    animation['card_data'] = card_data
                    break
    
    def _handle_use_item_animation(self, data: Dict[str, Any]):
        """处理物品使用动画"""
        # 获取目标信息
        target_id = data.get('target_id', '')
        card_id = data.get('card_id', '')
        hand_index = data.get('hand_index', -1)
        player_id = data.get('player_id', '')  # 获取操作玩家ID
        
        # 判断是己方还是对手
        is_my_animation = (player_id == self.player_id)
        
        # 计算手牌位置
        game_state = self.client.get_game_state()
        if not game_state:
            return
        
        if is_my_animation:
            # 己方的动画：从我的手牌飞出
            my_hand = self.client.get_my_hand()
            if not my_hand:
                return
            
            # 使用实际的手牌索引计算起始位置
            hand_y = self.renderer.design_height - self.renderer.card_height - 10
            total_width = len(my_hand) * self.renderer.card_width + (len(my_hand) - 1) * self.renderer.card_spacing
            start_x = self.renderer.design_width // 2 - total_width // 2
            
            if hand_index >= 0 and hand_index < len(my_hand):
                hand_start_x = start_x + hand_index * (self.renderer.card_width + self.renderer.card_spacing)
            else:
                hand_start_x = start_x + (len(my_hand) - 1) * (self.renderer.card_width + self.renderer.card_spacing)
            hand_start_y = hand_y
        else:
            # 对手的动画：从对手的手牌区域飞出
            hand_start_x = self.renderer.design_width // 2
            hand_start_y = 100  # 顶部手牌区域
        
        # 计算目标位置
        target_pos = None
        if target_id:
            target_pos = self._get_target_position(target_id)
        
        # 计算场地中央位置
        center_x = self.renderer.design_width // 2
        center_y = self.renderer.design_height // 2
        
        # 非指向性物品：没有目标，直接在中央展示后消失
        if not target_pos:
            target_pos = (center_x, center_y)
        
        # 创建三阶段物品使用动画
        animation_id = self.animation_manager.add_animation(
            'card_use_item',
            (hand_start_x, hand_start_y),
            target_pos,
            duration=1.5,
            center_x=center_x,
            center_y=center_y
        )
        
        # 添加卡牌数据
        card_data = self._get_card_data(card_id)
        for animation in self.animation_manager.animations:
            if animation['id'] == animation_id:
                animation['card_data'] = card_data
                break
    
    def _handle_attack_animation(self, data: Dict[str, Any]):
        """处理攻击动画"""
        attacker_id = data.get('attacker_id', '')
        target_id = data.get('target_id', '')
        attacker_damage = data.get('attacker_damage', 0)
        target_damage = data.get('target_damage', 0)
        attacker_dead = data.get('attacker_dead', False)
        target_dead = data.get('target_dead', False)
        
        print(f"[DEBUG] Attack animation received: attacker_id={attacker_id}, target_id={target_id}")
        print(f"[DEBUG] Attack animation: attacker_dead={attacker_dead}, target_dead={target_dead}")
        print(f"[DEBUG] Attack animation data: {data}")
        
        # 获取攻击者和目标位置
        # 优先使用服务器传递的位置信息
        attacker_pos_info = data.get('attacker_pos')
        if attacker_pos_info:
            attacker_pos = self._calculate_position_from_info(attacker_pos_info)
            print(f"[DEBUG] Using server position info: {attacker_pos_info} -> {attacker_pos}")
        else:
            attacker_pos = self._get_champion_position(attacker_id)
            print(f"[DEBUG] Using client position lookup: {attacker_pos}")
        
        # 获取目标位置
        target_pos_info = data.get('target_pos')
        if target_pos_info:
            target_pos = self._calculate_position_from_info(target_pos_info)
            print(f"[DEBUG] Using server target position info: {target_pos}")
        else:
            target_pos = self._get_target_position(target_id)
            print(f"[DEBUG] Using client target position lookup: {target_pos}")
        
        if attacker_pos and target_pos:
            print(f"[DEBUG] Creating attack animation with positions: {attacker_pos} -> {target_pos}")
            
            # 使用服务器传递的卡牌数据（如果存在），避免已移除的卡牌无法获取数据
            attacker_card_data = data.get('attacker_card_data')
            if not attacker_card_data:
                attacker_card_data = self._get_attacker_card_data(attacker_id)
            
            print(f"[DEBUG] Attacker card data: {attacker_card_data}")
            
            # 创建攻击动画
            animation_id = self.animation_manager.add_animation('attack', attacker_pos, target_pos, 0.8)
            print(f"[DEBUG] Created attack animation with ID: {animation_id}")
            
            # 添加攻击者卡牌数据和ID到动画
            if animation_id is not None:
                for animation in self.animation_manager.animations:
                    if animation['id'] == animation_id:
                        animation['attacker_id'] = attacker_id
                        animation['card_data'] = attacker_card_data
                        print(f"[DEBUG] Added card data to animation {animation_id}: {animation}")
                        break
            
            # 创建伤害数字动画
            if attacker_damage > 0:
                damage_pos = (target_pos[0] + self.renderer.card_width // 2, target_pos[1])
                self.animation_manager.add_damage_number_animation(damage_pos, attacker_damage)
            
            if target_damage > 0:
                damage_pos = (attacker_pos[0] + self.renderer.card_width // 2, attacker_pos[1])
                self.animation_manager.add_damage_number_animation(damage_pos, target_damage)
            
            # 处理死亡动画（延迟执行，等待攻击动画完成）
            if attacker_dead or target_dead:
                # 在攻击动画完成后触发死亡动画
                # 使用闭包避免变量绑定问题
                def make_death_callback(attacker_id, target_id, attacker_dead, target_dead):
                    return lambda: self._trigger_death_animations(attacker_id, target_id, attacker_dead, target_dead)
                
                death_callback = make_death_callback(attacker_id, target_id, attacker_dead, target_dead)
                
                # 找到攻击动画并添加完成回调
                for animation in self.animation_manager.animations:
                    if animation['id'] == animation_id:
                        animation['on_complete'] = death_callback
                        break
        else:
            print(f"[DEBUG] Failed to get positions: attacker={attacker_pos}, target={target_pos}")
    
    def _handle_death_animation(self, unit_id: str):
        """处理死亡动画"""
        # 获取单位位置
        unit_pos = self._get_champion_position(unit_id) or self._get_target_position(unit_id)
        if not unit_pos:
            return
        
        # 弃牌堆位置（屏幕左下角）
        discard_pos = (50, self.renderer.design_height - 50)
        
        # 创建死亡动画
        self.animation_manager.add_card_death_animation(unit_pos, discard_pos)
    
    def _get_target_position(self, target_id: str) -> Optional[Tuple[int, int]]:
        """获取目标位置"""
        if target_id.endswith("_summoner"):
            # 召唤师位置
            summoner_x = self.renderer.design_width // 2 - self.renderer.card_width // 2
            center_line = self.renderer.design_height // 2
            
            if target_id == f"{self.player_id}_summoner":
                # 己方召唤师
                summoner_y = center_line + 100 + self.renderer.card_height + 40 - 150
            else:
                # 对手召唤师
                summoner_y = center_line - 100 - self.renderer.card_height - 40 - self.renderer.card_height
            
            return (summoner_x, summoner_y)
        else:
            # 场上单位
            return self._get_champion_position(target_id)
    
    def _get_champion_position(self, champion_id: str) -> Optional[Tuple[int, int]]:
        """获取场上单位位置"""
        game_state = self.client.get_game_state()
        if not game_state:
            return None
        
        # 检查己方场地
        my_battlefield = self.client.get_my_battlefield()
        center_line = self.renderer.design_height // 2
        battlefield_y = center_line + 100 - 150
        
        my_champions = [c for c in my_battlefield if c is not None]
        if my_champions:
            total_width = len(my_champions) * self.renderer.card_width + (len(my_champions) - 1) * self.renderer.card_spacing
            start_x = self.renderer.design_width // 2 - total_width // 2
            
            rendered_index = 0
            for champion in my_champions:
                if (champion.get("instance_id") == champion_id or 
                    champion.get("card_id") == champion_id):
                    card_x = start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                    return (card_x, battlefield_y)
                rendered_index += 1
        
        # 检查对手场地
        opponent_battlefield = self.client.get_opponent_battlefield()
        opponent_battlefield_y = center_line - 100 - self.renderer.card_height
        opponent_champions = [c for c in opponent_battlefield if c is not None]
        
        if opponent_champions:
            total_width = len(opponent_champions) * self.renderer.card_width + (len(opponent_champions) - 1) * self.renderer.card_spacing
            start_x = self.renderer.design_width // 2 - total_width // 2
            
            rendered_index = 0
            for champion in opponent_champions:
                if (champion.get("instance_id") == champion_id or 
                    champion.get("card_id") == champion_id):
                    card_x = start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                    return (card_x, opponent_battlefield_y)
                rendered_index += 1
        
        return None
    
    def _get_card_data(self, card_id: str) -> Dict[str, Any]:
        """获取卡牌数据"""
        # 从卡牌注册表获取数据
        if card_id in self.renderer.card_display.card_registry:
            return self.renderer.card_display.card_registry[card_id].copy()
        
        # 如果注册表中没有，返回基本数据
        return {
            "card_id": card_id,
            "name": card_id,
            "type": "Unknown",
            "cost": 0,
            "attack": 0,
            "health": 0
        }
    
    def _get_attacker_card_data(self, attacker_id: str) -> Dict[str, Any]:
        """获取攻击者卡牌数据"""
        game_state = self.client.get_game_state()
        if not game_state:
            return None
        
        # 在己方场地查找
        my_battlefield = self.client.get_my_battlefield()
        for champion in my_battlefield:
            if champion and (champion.get("instance_id") == attacker_id or champion.get("card_id") == attacker_id):
                return champion
        
        # 在对手场地查找
        opponent_battlefield = self.client.get_opponent_battlefield()
        for champion in opponent_battlefield:
            if champion and (champion.get("instance_id") == attacker_id or champion.get("card_id") == attacker_id):
                return champion
        
        return None
    
    def _calculate_position_from_info(self, pos_info: Dict[str, Any]) -> Optional[Tuple[int, int]]:
        """根据服务器传递的位置信息计算实际坐标"""
        player_id = pos_info.get('player_id')
        rendered_index = pos_info.get('rendered_index')
        champions_count = pos_info.get('champions_count')
        
        print(f"[DEBUG] _calculate_position_from_info: player_id={player_id}, rendered_index={rendered_index}, champions_count={champions_count}")
        
        if player_id is None or rendered_index is None or champions_count is None:
            print(f"[DEBUG] Missing required info")
            return None
        
        # 客户端自己判断是否为对手
        is_opponent = (player_id != self.player_id)
        
        # 计算场地位置
        center_line = self.renderer.design_height // 2
        
        if is_opponent:
            # 对手场地
            battlefield_y = center_line - 100 - self.renderer.card_height
        else:
            # 己方场地
            battlefield_y = center_line + 100 - 150
        
        # 计算坐标（使用服务器预计算的索引）
        total_width = champions_count * self.renderer.card_width + (champions_count - 1) * self.renderer.card_spacing
        start_x = self.renderer.design_width // 2 - total_width // 2
        card_x = start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
        
        result = (card_x, battlefield_y)
        print(f"[DEBUG] Calculated position: {result}")
        return result
    
    def _get_champion_position_from_data(self, champion_id: str, data: Dict[str, Any]) -> Optional[Tuple[int, int]]:
        """从服务器数据中获取攻击者位置（fallback方法）"""
        game_state = self.client.get_game_state()
        if not game_state:
            return None
        
        # 尝试从battlefield查找位置
        position = self._get_champion_position(champion_id)
        if position:
            return position
        
        # 如果失败，使用最近一次已知位置或估计位置
        # 这是最后的备选方案
        center_line = self.renderer.design_height // 2
        battlefield_y = center_line - 50
        return (self.renderer.design_width // 2, battlefield_y)
    
    def _trigger_death_animations(self, attacker_id: str, target_id: str, attacker_dead: bool, target_dead: bool):
        """触发死亡动画（延迟执行）"""
        if attacker_dead:
            self._handle_death_animation(attacker_id)
        if target_dead:
            self._handle_death_animation(target_id)
    
    def _render_animations(self):
        """渲染动画中的卡牌和效果"""
        active_animations = self.animation_manager.get_active_animations()
        
        for animation in active_animations:
            animation_type = animation.get('type')
            current_pos = animation.get('current_pos')
            
            if not current_pos:
                continue
            
            if animation_type in ['card_summon', 'card_use_item', 'card_death']:
                # 渲染飞行中的卡牌
                card_data = animation.get('card_data', {})
                if card_data:
                    scale = animation.get('scale', 1.0)
                    alpha = animation.get('alpha', 255)
                    self.renderer.render_animated_card(card_data, current_pos, scale, alpha)
            
            elif animation_type == 'attack':
                # 渲染攻击动画（攻击者移动到目标处）
                card_data = animation.get('card_data', {})
                if card_data:
                    # 在当前位置渲染完整的攻击者卡牌
                    # 注意：current_pos 已经是卡牌左上角坐标
                    self.renderer.render_animated_card(card_data, current_pos, 1.0, 255)
            
            elif animation_type == 'damage_number':
                # 渲染伤害数字
                damage = animation.get('damage', 0)
                alpha = animation.get('alpha', 255)
                self.renderer.render_damage_number(damage, current_pos, alpha)
    
    async def _check_summoner_click(self, pos, game_state):
        """检查是否点击了召唤师（目标选择状态）"""
        players = game_state.get("players", {})
        
        # 使用与渲染器相同的位置计算
        summoner_x = self.renderer.design_width // 2 - self.renderer.card_width // 2
        center_line = self.renderer.design_height // 2
        
        # 检查己方召唤师（上移150px为手牌留空间）
        my_summoner_y = center_line + 100 + self.renderer.card_height + 40 - 150
        my_summoner_rect = pygame.Rect(summoner_x, my_summoner_y, self.renderer.card_width, self.renderer.card_height)
        
        if my_summoner_rect.collidepoint(pos):
            summoner_id = f"{self.player_id}_summoner"
            # 检查是否是有效目标
            if any(t["id"] == summoner_id for t in self.valid_targets):
                self.selected_target = summoner_id
                self.interaction_state = "CARD_SELECTED"
                return True
        
        # 检查对手召唤师（保持对称位置）
        opponent_id = None
        for pid in players.keys():
            if pid != self.player_id:
                opponent_id = pid
                break
        
        if opponent_id:
            opponent_summoner_y = center_line - 100 - self.renderer.card_height - 40 - self.renderer.card_height
            opponent_summoner_rect = pygame.Rect(summoner_x, opponent_summoner_y, self.renderer.card_width, self.renderer.card_height)
            
            if opponent_summoner_rect.collidepoint(pos):
                summoner_id = f"{opponent_id}_summoner"
                # 检查是否是有效目标
                if any(t["id"] == summoner_id for t in self.valid_targets):
                    self.selected_target = summoner_id
                    self.interaction_state = "CARD_SELECTED"
                    return True
        
        return False
    
    async def _check_battlefield_click(self, pos, game_state):
        """检查是否点击了场上单位（目标选择状态）"""
        my_battlefield = self.client.get_my_battlefield()
        opponent_battlefield = self.client.get_opponent_battlefield()
        
        center_line = self.renderer.design_height // 2
        
        # 检查己方场地（动态居中，上移150px）
        my_battlefield_y = center_line + 100 - 150
        my_champions = [c for c in my_battlefield if c is not None]
        if my_champions:
            my_total_width = len(my_champions) * self.renderer.card_width + (len(my_champions) - 1) * self.renderer.card_spacing
            my_start_x = self.renderer.design_width // 2 - my_total_width // 2
            
            rendered_index = 0
            for champion in my_champions:
                card_x = my_start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                card_y = my_battlefield_y
                card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                rendered_index += 1
                
                if card_rect.collidepoint(pos):
                    champion_id = champion.get("instance_id") or champion.get("card_id")
                    # 检查是否是有效目标
                    if any(t["id"] == champion_id for t in self.valid_targets):
                        self.selected_target = champion_id
                        self.interaction_state = "CARD_SELECTED"
                        return True
        
        # 检查对手场地（动态居中，镜像对称）
        opponent_battlefield_y = center_line - 100 - self.renderer.card_height
        opponent_champions = [c for c in opponent_battlefield if c is not None]
        if opponent_champions:
            opponent_total_width = len(opponent_champions) * self.renderer.card_width + (len(opponent_champions) - 1) * self.renderer.card_spacing
            opponent_start_x = self.renderer.design_width // 2 - opponent_total_width // 2
            
            rendered_index = 0
            for champion in opponent_champions:
                card_x = opponent_start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                card_y = opponent_battlefield_y
                card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                rendered_index += 1
                
                if card_rect.collidepoint(pos):
                    champion_id = champion.get("instance_id") or champion.get("card_id")
                    # 检查是否是有效目标
                    if any(t["id"] == champion_id for t in self.valid_targets):
                        self.selected_target = champion_id
                        self.interaction_state = "CARD_SELECTED"
                        return True
        
        return False
    
    async def handle_playing_click(self, pos, game_state):
        """处理游戏阶段的点击"""
        # 检查确认/取消按钮
        if self.interaction_state == "CARD_SELECTED":
            # 确认按钮
            confirm_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 110, 100, 40)
            # 取消按钮
            cancel_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 160, 100, 40)
            
            if confirm_button_rect.collidepoint(pos):
                # 确认执行动作
                await self._execute_pending_action()
                self._reset_interaction_state()
                return
            elif cancel_button_rect.collidepoint(pos):
                # 取消选择
                self._reset_interaction_state()
                return
        
        # 在目标选择状态下，检查目标点击
        if self.interaction_state == "TARGET_SELECTION":
            # 检查是否点击了召唤师
            if await self._check_summoner_click(pos, game_state):
                return
            
            # 检查是否点击了场上单位
            if await self._check_battlefield_click(pos, game_state):
                return
            
            # 点击了其他地方，取消选择
            cancel_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 160, 100, 40)
            if cancel_button_rect.collidepoint(pos):
                self._reset_interaction_state()
                return
        
        # 检查结束回合按钮（只有在IDLE状态时才能点击）
        if self.interaction_state == "IDLE":
            button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 60, 100, 40)
            if button_rect.collidepoint(pos):
                await self.client.send_end_turn()
                return
        
        # 检查手牌点击（只在IDLE状态下）
        if self.interaction_state == "IDLE":
            my_hand = self.client.get_my_hand()
            
            # 手牌位置 - 在最底部
            hand_y = self.renderer.design_height - self.renderer.card_height - 10
            total_width = len(my_hand) * self.renderer.card_width + (len(my_hand) - 1) * self.renderer.card_spacing
            start_x = self.renderer.design_width // 2 - total_width // 2
            
            for i, card in enumerate(my_hand):
                card_x = start_x + i * (self.renderer.card_width + self.renderer.card_spacing)
                card_y = hand_y
                card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                
                if card_rect.collidepoint(pos):
                    # 选中卡牌
                    self.pending_card_data = card
                    self.pending_card = card.get("instance_id") or card.get("card_id")
                    
                    # 判断是否需要选择目标
                    if self._card_needs_target(card):
                        self.interaction_state = "TARGET_SELECTION"
                        if card.get("type") == "Champion":
                            self.pending_action = "SUMMON"
                        else:
                            self.pending_action = "USE_ITEM"
                        self.valid_targets = self._get_valid_targets_for_card(card)
                    else:
                        self.interaction_state = "CARD_SELECTED"
                        if card.get("type") == "Champion":
                            self.pending_action = "SUMMON"
                        else:
                            self.pending_action = "USE_ITEM"
                    return
        
        # 检查场地点击（只在IDLE状态下可以选择己方单位发起攻击）
        if self.interaction_state == "IDLE":
            my_battlefield = self.client.get_my_battlefield()
            
            # 我的场地 - 使用与渲染器相同的位置计算（上移150px）
            center_line = self.renderer.design_height // 2
            battlefield_y = center_line + 100 - 150
            my_champions = [c for c in my_battlefield if c is not None]
            
            if my_champions:
                total_width = len(my_champions) * self.renderer.card_width + (len(my_champions) - 1) * self.renderer.card_spacing
                start_x = self.renderer.design_width // 2 - total_width // 2
                
                rendered_index = 0
                for champion in my_champions:
                    card_x = start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                    card_y = battlefield_y
                    card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                    rendered_index += 1
                    
                    if card_rect.collidepoint(pos):
                        # 检查是否可以攻击
                        if self.client.is_my_turn() and champion.get("can_attack_this_turn", False):
                            self.interaction_state = "TARGET_SELECTION"
                            self.pending_action = "ATTACK"
                            self.pending_card = champion.get("instance_id") or champion.get("card_id")
                            self.pending_card_data = champion
                            self.valid_targets = self._get_valid_attack_targets()
                        return
    
    async def handle_card_click(self, card, game_state):
        """处理卡牌点击"""
        card_type = card.get("type", "")
        
        if card_type == "Champion":
            # 召唤Champion
            if self.client.is_my_turn():
                # 查找空位置
                my_battlefield = self.client.get_my_battlefield()
                empty_position = None
                for i, champion in enumerate(my_battlefield):
                    if champion is None:
                        empty_position = i
                        break
                
                if empty_position is not None:
                    # 检查是否是Guard
                    guard_cards = ["test_guard", "zhen_ji", "sun_ce", "zhou_yu", "zhang_liang", "hua_mulan", "liu_bei", "lu_ban", "diao_chan", "li_shuwen", "liu_bang"]
                    if card.get("card_id") in guard_cards:
                        # Guard需要选择守卫目标
                        await self.select_guard_target(card, empty_position)
                    # 检查是否是Xi Shi
                    elif card.get("card_id") == "xi_shi":
                        # Xi Shi需要选择效果目标
                        await self.select_effect_target(card, empty_position)
                    else:
                        await self.client.send_summon(card.get("card_id"), empty_position)
        
        elif card_type == "Item":
            # 使用Item
            if self.client.is_my_turn():
                if card.get("target_required", False):
                    # 需要选择目标
                    await self.select_item_target(card)
                else:
                    await self.client.send_use_item(card.get("card_id"))
    
    async def handle_champion_click(self, champion, game_state):
        """处理Champion点击"""
        if self.client.is_my_turn() and champion.get("can_attack_this_turn", False):
            # 选择攻击目标 - 使用新的交互状态系统
            self.interaction_state = "TARGET_SELECTION"
            self.pending_card = champion.get("card_id")
            self.pending_action = "ATTACK"
            self.valid_targets = self._get_valid_attack_targets()
            self.highlight_attack_targets()
    
    async def handle_target_click(self, target, game_state):
        """处理目标点击"""
        if self.interaction_state == "TARGET_SELECTION" and self.pending_action == "ATTACK":
            # 执行攻击 - 使用新的交互状态系统
            await self.client.send_attack(self.pending_card, target.get("instance_id"))
            self.interaction_state = "IDLE"
            self.clear_highlights()
    
    async def select_effect_target(self, card, position):
        """选择卡牌的效果目标（如Xi Shi）"""
        self.interaction_state = "TARGET_SELECTION"
        self.pending_card = card.get("card_id")
        self.pending_card_data = card
        self.pending_action = "SUMMON"
        self.selected_target = None
        
        # 获取有效的敌方目标
        self.valid_targets = self._get_valid_effect_targets()
        
        if not self.valid_targets:
            self.show_message("No valid targets for this card", "red")
            self.interaction_state = "IDLE"
            return
        
        self.show_message("Select target for " + card.get("name", "card"), "blue")
    
    async def select_guard_target(self, guard_card, position):
        """选择Guard的守卫目标"""
        # 设置目标选择状态
        self.interaction_state = "TARGET_SELECTION"
        self.pending_card = guard_card.get("card_id")
        self.pending_card_data = guard_card
        self.pending_action = "SUMMON"
        self.selected_target = None
        self.pending_position = position
        
        # 获取有效的守卫目标
        self.valid_targets = self._get_valid_targets_for_card(guard_card)
        
        if not self.valid_targets:
            self.show_message("No valid targets for this Guard", "red")
            self.interaction_state = "IDLE"
            return
        
        self.show_message("Select target to guard for " + guard_card.get("name", "Guard"), "blue")
    
    async def select_item_target(self, item_card):
        """选择Item的目标"""
        # 简化实现：默认选择召唤师
        summoner_id = f"{self.player_id}_summoner"
        await self.client.send_use_item(item_card.get("card_id"), summoner_id)
    
    def highlight_attack_targets(self):
        """高亮可攻击目标"""
        # 这里可以实现高亮逻辑
        pass
    
    def clear_highlights(self):
        """清除高亮"""
        pass
    
    def show_card_tooltip(self, pos):
        """显示卡牌提示框"""
        game_state = self.client.get_game_state()
        if not game_state:
            return
        
        # 检查是否在换牌阶段
        if self.client.is_mulligan_phase():
            self._check_mulligan_card_tooltip(pos, game_state)
        # 检查是否在游戏阶段
        elif self.client.is_playing_phase():
            self._check_playing_card_tooltip(pos, game_state)
    
    def _check_mulligan_card_tooltip(self, pos, game_state):
        """检查换牌阶段的卡牌详情"""
        mulligan_cards = game_state.get("mulligan_cards", [])
        
        # 计算手牌位置（与渲染器保持一致）
        card_y = 100  # 与渲染器中的y坐标一致
        total_width = len(mulligan_cards) * self.renderer.card_width + (len(mulligan_cards) - 1) * self.renderer.card_spacing
        start_x = self.renderer.design_width // 2 - total_width // 2
        
        for i, card in enumerate(mulligan_cards):
            card_x = start_x + i * (self.renderer.card_width + self.renderer.card_spacing)
            card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
            
            if card_rect.collidepoint(pos):
                # 如果card是字符串（card_id），从card_registry获取完整数据
                if isinstance(card, str):
                    card_id = card
                    if card_id in self.renderer.card_display.card_registry:
                        self.card_tooltip = self.renderer.card_display.card_registry[card_id]
                    else:
                        # 如果注册表中没有，创建一个基本的卡牌数据
                        self.card_tooltip = {
                            "name": card_id,
                            "description": "No description available",
                            "type": "Unknown",
                            "card_id": card_id
                        }
                else:
                    # 如果card已经是字典，直接使用
                    self.card_tooltip = card
                self.tooltip_timer = self.tooltip_duration
                return
    
    def _check_playing_card_tooltip(self, pos, game_state):
        """检查游戏阶段的卡牌详情"""
        players = game_state.get("players", {})
        my_data = players.get(self.player_id, {})
        
        # 检查手牌
        hand = my_data.get("hand", [])
        hand_y = self.renderer.design_height // 2 + self.renderer.design_height // 2 - self.renderer.card_height - 20
        total_width = len(hand) * self.renderer.card_width + (len(hand) - 1) * self.renderer.card_spacing
        start_x = self.renderer.design_width // 2 - total_width // 2
        
        for i, card in enumerate(hand):
            card_x = start_x + i * (self.renderer.card_width + self.renderer.card_spacing)
            card_y = hand_y
            card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
            
            if card_rect.collidepoint(pos):
                self.card_tooltip = card
                self.tooltip_timer = self.tooltip_duration
                return
        
        # 检查己方场地
        my_battlefield = my_data.get("battlefield", [])
        # 使用与渲染器相同的位置计算
        center_line = self.renderer.design_height // 2
        my_battlefield_y = center_line + 100 - 150
        
        my_champions = [c for c in my_battlefield if c is not None]
        if my_champions:
            my_total_width = len(my_champions) * self.renderer.card_width + (len(my_champions) - 1) * self.renderer.card_spacing
            my_start_x = self.renderer.design_width // 2 - my_total_width // 2
            
            rendered_index = 0
            for champion in my_champions:
                card_x = my_start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                card_y = my_battlefield_y
                card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                
                if card_rect.collidepoint(pos):
                    self.card_tooltip = champion
                    self.tooltip_timer = self.tooltip_duration
                    return
                rendered_index += 1
        
        # 检查敌方场地
        opponent_id = self.client.get_opponent_id()
        if opponent_id:
            opponent_data = players.get(opponent_id, {})
            opponent_battlefield = opponent_data.get("battlefield", [])
            # 使用与渲染器相同的位置计算
            center_line = self.renderer.design_height // 2
            opponent_battlefield_y = center_line - 100 - self.renderer.card_height
            
            opponent_champions = [c for c in opponent_battlefield if c is not None]
            if opponent_champions:
                opponent_total_width = len(opponent_champions) * self.renderer.card_width + (len(opponent_champions) - 1) * self.renderer.card_spacing
                opponent_start_x = self.renderer.design_width // 2 - opponent_total_width // 2
                
                rendered_index = 0
                for champion in opponent_champions:
                    card_x = opponent_start_x + rendered_index * (self.renderer.card_width + self.renderer.card_spacing)
                    card_y = opponent_battlefield_y
                    card_rect = pygame.Rect(card_x, card_y, self.renderer.card_width, self.renderer.card_height)
                    
                    if card_rect.collidepoint(pos):
                        self.card_tooltip = champion
                        self.tooltip_timer = self.tooltip_duration
                        return
                    rendered_index += 1
        
        # 检查己方召唤师
        my_summoner = my_data.get("summoner", {})
        if my_summoner:
            center_line = self.renderer.design_height // 2
            summoner_x = self.renderer.design_width // 2 - self.renderer.card_width // 2
            summoner_y = center_line + 100 + self.renderer.card_height + 40 - 150
            summoner_rect = pygame.Rect(summoner_x, summoner_y, self.renderer.card_width, self.renderer.card_height)
            
            if summoner_rect.collidepoint(pos):
                self.card_tooltip = my_summoner
                self.tooltip_timer = self.tooltip_duration
                return
        
        # 检查敌方召唤师
        if opponent_id:
            opponent_summoner = opponent_data.get("summoner", {})
            if opponent_summoner:
                center_line = self.renderer.design_height // 2
                summoner_x = self.renderer.design_width // 2 - self.renderer.card_width // 2
                summoner_y = center_line - 100 - self.renderer.card_height - 40 - self.renderer.card_height
                summoner_rect = pygame.Rect(summoner_x, summoner_y, self.renderer.card_width, self.renderer.card_height)
                
                if summoner_rect.collidepoint(pos):
                    self.card_tooltip = opponent_summoner
                    self.tooltip_timer = self.tooltip_duration
                    return
    
    async def handle_game_release(self, pos):
        """处理游戏中的鼠标释放"""
        # 处理拖拽释放
        pass
    
    def render(self):
        """渲染游戏"""
        if self.input_mode == "server_url":
            self.render_server_input()
        elif self.input_mode == "room_manager":
            self.render_room_manager()
        elif self.input_mode == "custom_deck_editor":
            self.render_custom_deck_editor()
        elif self.input_mode == "game_over":
            self.render_game_over()
        elif self.input_mode == "playing":
            game_state = self.client.get_game_state()
            
            # 先调用render_game，但不flip（在render_game内部已经flip了）
            # 我们需要在flip之前渲染按钮
            self.renderer.render_game_without_flip(
                game_state, 
                self.player_id, 
                self.selected_cards,
                interaction_state=self.interaction_state,
                valid_targets=self.valid_targets,
                selected_target=self.selected_target,
                pending_card_name=self.pending_card_data.get("name") if self.pending_card_data else None,
                available_decks=self.client.get_available_decks()
            )
            
            # 渲染按钮（在flip之前）
            if self.interaction_state == "CARD_SELECTED":
                self.render_confirm_dialog()
            elif self.interaction_state == "TARGET_SELECTION":
                self.render_target_selection_ui()
            
            # 渲染消息提示
            if self.message_text and self.message_timer > 0:
                self.render_message()
            
            # 渲染卡牌详情
            if self.card_tooltip and self.tooltip_timer > 0:
                self.render_card_tooltip()
            
            # 渲染Flag选择界面
            if self.flag_choice_required:
                self.render_flag_choice_ui()
            
            # 渲染动画中的卡牌和效果
            self._render_animations()
            
            # 缩放并显示
            self.renderer._scale_and_display()
            # 最后flip
            pygame.display.flip()
    
    def render_message(self):
        """Render game message at bottom center of screen"""
        if not self.message_text:
            return
        
        # Render message text
        message_surface = self.renderer.title_font.render(self.message_text, True, self.message_color)
        
        # Create background with padding
        bg_width = message_surface.get_width() + 40
        bg_height = message_surface.get_height() + 20
        bg_surface = pygame.Surface((bg_width, bg_height))
        bg_surface.fill(self.renderer.colors['black'])
        bg_surface.set_alpha(220)
        
        # Position at bottom center
        bg_x = self.renderer.design_width // 2 - bg_width // 2
        bg_y = self.renderer.design_height - bg_height - 80
        
        # Draw background and text
        self.renderer.virtual_surface.blit(bg_surface, (bg_x, bg_y))
        text_x = self.renderer.design_width // 2 - message_surface.get_width() // 2
        text_y = bg_y + 10
        self.renderer.virtual_surface.blit(message_surface, (text_x, text_y))
    
    def render_card_tooltip(self):
        """渲染卡牌详情提示框"""
        if not self.card_tooltip or self.tooltip_timer <= 0:
            return
        
        # 获取卡牌信息
        card_name = self.card_tooltip.get("name", "Unknown")
        card_description = self.card_tooltip.get("description", "No description")
        card_type = self.card_tooltip.get("type", "Unknown")
        
        # 确定子类别
        card_subtype = "Unknown"
        if card_type == "Champion":
            # 根据卡牌ID确定子类别
            card_id = self.card_tooltip.get("card_id", "")
            
            # 骑士类
            rider_cards = ["wei_qing", "meng_tian", "qin_liangyu", "ying_zheng", "sun_quan", "test_rider", "liang_hongyu", "xu_fu", "da_ji"]
            if "rider" in card_id or card_id in rider_cards:
                card_subtype = "Rider"
            # 守卫类
            elif "guard" in card_id or card_id in ["zhen_ji", "sun_ce", "zhou_yu", "zhang_liang", "hua_mulan", "liu_bei", "lu_ban", "diao_chan", "li_shuwen", "liu_bang", "test_guard"]:
                card_subtype = "Guard"
            # 法师类
            elif "mage" in card_id or card_id in ["xiao_qiao", "mi_yue", "test_mage"]:
                card_subtype = "Mage"
            # 刺客类
            elif "assassin" in card_id or card_id in ["jing_ke", "dragon", "test_assassin"]:
                card_subtype = "Assassin"
            # 战士类
            elif "warrior" in card_id or card_id in ["da_qiao", "han_xin", "xi_shi", "test_warrior", "yang_yuhuan", "bai_qi", "wu_zetian"]:
                card_subtype = "Warrior"
            # 默认显示为Champion
            else:
                card_subtype = "Champion"
                
        elif card_type == "Item":
            card_subtype = "Item"
        elif card_type == "Summoner":
            card_subtype = "Summoner"
        
        # 获取卡牌属性
        cost = self.card_tooltip.get("cost", 0)
        attack = self.card_tooltip.get("attack", 0)
        hp = self.card_tooltip.get("hp", 0)
        
        # 计算提示框大小和位置
        tooltip_width = 300
        tooltip_height = 200
        tooltip_x = self.renderer.design_width - tooltip_width - 20
        tooltip_y = 100  # 往下移动，避免挡住右上角信息
        
        # 绘制提示框背景
        tooltip_rect = pygame.Rect(tooltip_x, tooltip_y, tooltip_width, tooltip_height)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['light_gray'], tooltip_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], tooltip_rect, 2)
        
        # 绘制卡牌名称
        name_text = self.renderer.normal_font.render(card_name, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(name_text, (tooltip_x + 10, tooltip_y + 10))
        
        # 绘制类别和子类别
        type_text = f"Type: {card_type}"
        if card_subtype != "Unknown":
            type_text += f" ({card_subtype})"
        type_surface = self.renderer.small_font.render(type_text, True, self.renderer.colors['dark_gray'])
        self.renderer.virtual_surface.blit(type_surface, (tooltip_x + 10, tooltip_y + 35))
        
        # 绘制属性（如果是Champion）
        if card_type == "Champion":
            stats_text = f"Cost: {cost} | Attack: {attack} | HP: {hp}"
            stats_surface = self.renderer.small_font.render(stats_text, True, self.renderer.colors['dark_gray'])
            self.renderer.virtual_surface.blit(stats_surface, (tooltip_x + 10, tooltip_y + 55))
        
        # 绘制描述
        description_y = tooltip_y + 80
        description_lines = self._wrap_text(card_description, self.renderer.small_font, tooltip_width - 20)
        for line in description_lines:
            desc_surface = self.renderer.small_font.render(line, True, self.renderer.colors['black'])
            self.renderer.virtual_surface.blit(desc_surface, (tooltip_x + 10, description_y))
            description_y += 20
            if description_y > tooltip_y + tooltip_height - 20:
                break
    
    def _wrap_text(self, text, font, max_width):
        """将文本换行以适应指定宽度"""
        words = text.split(' ')
        lines = []
        current_line = []
        
        for word in words:
            test_line = ' '.join(current_line + [word])
            if font.size(test_line)[0] <= max_width:
                current_line.append(word)
            else:
                if current_line:
                    lines.append(' '.join(current_line))
                    current_line = [word]
                else:
                    lines.append(word)
        
        if current_line:
            lines.append(' '.join(current_line))
        
        return lines
    
    def set_flag_choice_required(self, choices):
        """设置Flag选择状态"""
        self.flag_choice_required = True
        self.flag_choices = choices
        self.pending_flag_card = "flag"  # 假设是Flag道具
    
    def handle_flag_choice(self, choice_id):
        """处理Flag选择"""
        if not self.flag_choice_required:
            return
        
        # 发送选择结果到服务器
        asyncio.create_task(self.client.send_flag_choice(choice_id))
        
        # 重置状态
        self.flag_choice_required = False
        self.flag_choices = []
        self.pending_flag_card = None
    
    def render_flag_choice_ui(self):
        """渲染Flag选择界面"""
        if not self.flag_choices:
            return
        
        # 计算选择界面位置（屏幕中央）
        choice_width = 400
        choice_height = 200
        choice_x = self.renderer.design_width // 2 - choice_width // 2
        choice_y = self.renderer.design_height // 2 - choice_height // 2
        
        # 绘制背景
        choice_rect = pygame.Rect(choice_x, choice_y, choice_width, choice_height)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['light_gray'], choice_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], choice_rect, 3)
        
        # 绘制标题
        title_text = self.renderer.normal_font.render("Choose Flag Effect:", True, self.renderer.colors['black'])
        title_rect = title_text.get_rect(center=(choice_x + choice_width // 2, choice_y + 30))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 绘制选择按钮
        button_width = 300
        button_height = 40
        button_spacing = 60
        
        for i, choice in enumerate(self.flag_choices):
            button_x = choice_x + (choice_width - button_width) // 2
            button_y = choice_y + 60 + i * button_spacing
            button_rect = pygame.Rect(button_x, button_y, button_width, button_height)
            
            # 绘制按钮背景
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], button_rect)
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], button_rect, 2)
            
            # 绘制按钮文本
            button_text = self.renderer.small_font.render(choice.get("description", ""), True, self.renderer.colors['white'])
            text_rect = button_text.get_rect(center=button_rect.center)
            self.renderer.virtual_surface.blit(button_text, text_rect)
    
    def render_target_selection_ui(self):
        """Render target selection UI (only cancel button)"""
        # Cancel button - above end turn button
        cancel_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 160, 100, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], cancel_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], cancel_button_rect, 2)
        cancel_text = self.renderer.normal_font.render("Cancel", True, self.renderer.colors['white'])
        cancel_text_rect = cancel_text.get_rect(center=cancel_button_rect.center)
        self.renderer.virtual_surface.blit(cancel_text, cancel_text_rect)
    
    def render_confirm_dialog(self):
        """Render confirm/cancel buttons (in bottom right corner)"""
        # Cancel button - above end turn
        cancel_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 160, 100, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], cancel_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], cancel_button_rect, 2)
        cancel_text = self.renderer.normal_font.render("Cancel", True, self.renderer.colors['white'])
        cancel_text_rect = cancel_text.get_rect(center=cancel_button_rect.center)
        self.renderer.virtual_surface.blit(cancel_text, cancel_text_rect)
        
        # Confirm button - below cancel button
        confirm_button_rect = pygame.Rect(self.renderer.design_width - 120, self.renderer.design_height - 110, 100, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], confirm_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], confirm_button_rect, 2)
        confirm_text = self.renderer.normal_font.render("Confirm", True, self.renderer.colors['white'])
        confirm_text_rect = confirm_text.get_rect(center=confirm_button_rect.center)
        self.renderer.virtual_surface.blit(confirm_text, confirm_text_rect)
    
    def render_server_input(self):
        """渲染服务器地址输入"""
        self.renderer.virtual_surface.fill(self.renderer.colors['light_gray'])
        
        # 标题
        title_text = self.renderer.title_font.render("LOCA2", True, self.renderer.colors['black'])
        title_rect = title_text.get_rect(center=(self.renderer.design_width // 2, 200))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 输入提示
        prompt_text = self.renderer.normal_font.render("Enter server address(right click to paste):", True, self.renderer.colors['black'])
        prompt_rect = prompt_text.get_rect(center=(self.renderer.design_width // 2, 250))
        self.renderer.virtual_surface.blit(prompt_text, prompt_rect)
        
        # 输入框（居中）
        input_width = 400
        input_height = 40
        input_x = self.renderer.design_width // 2 - input_width // 2
        input_rect = pygame.Rect(input_x, 300, input_width, input_height)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], input_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], input_rect, 2)
        
        # 输入文本
        input_text = self.input_font.render(self.server_url_input, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(input_text, (input_rect.x + 5, input_rect.y + 5))
        
        # 右键粘贴提示
        paste_hint = self.renderer.small_font.render("右键点击输入框可粘贴地址", True, self.renderer.colors['dark_gray'])
        paste_hint_rect = paste_hint.get_rect(center=(self.renderer.design_width // 2, 360))
        self.renderer.virtual_surface.blit(paste_hint, paste_hint_rect)
        
        # 确认按钮
        confirm_rect = pygame.Rect(self.renderer.design_width // 2 - 60, 350, 120, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], confirm_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], confirm_rect, 2)
        
        confirm_text = self.renderer.normal_font.render("Confirm", True, self.renderer.colors['white'])
        confirm_text_rect = confirm_text.get_rect(center=confirm_rect.center)
        self.renderer.virtual_surface.blit(confirm_text, confirm_text_rect)
        
        # 提示
        hint_text = self.renderer.small_font.render("Example: ws://localhost:8001", True, self.renderer.colors['gray'])
        hint_rect = hint_text.get_rect(center=(self.renderer.design_width // 2, 410))
        self.renderer.virtual_surface.blit(hint_text, hint_rect)
        
        # 缩放并显示
        self.renderer._scale_and_display()
        pygame.display.flip()
    
    def render_room_manager(self):
        """渲染房间管理界面"""
        self.renderer.virtual_surface.fill(self.renderer.colors['light_gray'])
        
        # 左侧区域（约40%宽度）
        left_width = int(self.renderer.design_width * 0.4)
        right_start = left_width
        
        # 绘制分割线
        pygame.draw.line(self.renderer.virtual_surface, self.renderer.colors['black'], 
                        (left_width, 0), (left_width, self.renderer.design_height), 2)
        
        # 左侧区域 - 房间列表
        # 标题
        title_text = self.renderer.title_font.render("Available Rooms", True, self.renderer.colors['black'])
        title_rect = title_text.get_rect(center=(left_width // 2, 50))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 房间列表
        room_list_start_y = 100
        room_item_height = 30
        
        for i, room in enumerate(self.rooms_list):
            room_y = room_list_start_y + i * room_item_height
            
            # 房间项背景
            room_rect = pygame.Rect(20, room_y, left_width - 40, room_item_height)
            if room["room_id"] == self.selected_room_id:
                # 选中状态
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], room_rect)
            else:
                # 普通状态
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], room_rect)
            
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], room_rect, 1)
            
            # 房间信息文本
            room_text = f"Room: {room['room_id']} ({room['player_count']}/2)"
            room_text_surface = self.renderer.normal_font.render(room_text, True, self.renderer.colors['black'])
            text_rect = room_text_surface.get_rect(center=room_rect.center)
            self.renderer.virtual_surface.blit(room_text_surface, text_rect)
        
        # 刷新按钮
        refresh_button_rect = pygame.Rect(20, self.renderer.design_height - 60, 100, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], refresh_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], refresh_button_rect, 2)
        
        refresh_text = self.renderer.normal_font.render("Refresh", True, self.renderer.colors['white'])
        refresh_text_rect = refresh_text.get_rect(center=refresh_button_rect.center)
        self.renderer.virtual_surface.blit(refresh_text, refresh_text_rect)
        
        # 右侧区域 - 创建和加入房间
        # 创建房间区域
        create_section_y = 200
        create_title_text = self.renderer.title_font.render("Create New Room", True, self.renderer.colors['black'])
        create_title_rect = create_title_text.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, create_section_y))
        self.renderer.virtual_surface.blit(create_title_text, create_title_rect)
        
        # 输入提示
        create_prompt_text = self.renderer.normal_font.render("Enter Room ID:", True, self.renderer.colors['black'])
        create_prompt_rect = create_prompt_text.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, create_section_y + 30))
        self.renderer.virtual_surface.blit(create_prompt_text, create_prompt_rect)
        
        # 输入框
        create_input_rect = pygame.Rect(right_start + 20, create_section_y + 50, 300, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], create_input_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], create_input_rect, 2)
        
        # 输入文本
        create_input_text = self.renderer.normal_font.render(self.create_room_input, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(create_input_text, (create_input_rect.x + 5, create_input_rect.y + 5))
        
        # 创建房间按钮
        create_button_rect = pygame.Rect(right_start + 20, create_section_y + 100, 120, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], create_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], create_button_rect, 2)
        
        create_button_text = self.renderer.normal_font.render("Create Room", True, self.renderer.colors['white'])
        create_button_text_rect = create_button_text.get_rect(center=create_button_rect.center)
        self.renderer.virtual_surface.blit(create_button_text, create_button_text_rect)
        
        # 加入房间区域
        join_section_y = 350
        join_title_text = self.renderer.title_font.render("Join Selected Room", True, self.renderer.colors['black'])
        join_title_rect = join_title_text.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, join_section_y))
        self.renderer.virtual_surface.blit(join_title_text, join_title_rect)
        
        # 显示选中的房间
        if self.selected_room_id:
            selected_text = f"Selected: Room {self.selected_room_id}"
            selected_text_surface = self.renderer.normal_font.render(selected_text, True, self.renderer.colors['blue'])
            selected_text_rect = selected_text_surface.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, join_section_y + 30))
            self.renderer.virtual_surface.blit(selected_text_surface, selected_text_rect)
        else:
            no_selection_text = "No room selected"
            no_selection_text_surface = self.renderer.normal_font.render(no_selection_text, True, self.renderer.colors['gray'])
            no_selection_text_rect = no_selection_text_surface.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, join_section_y + 30))
            self.renderer.virtual_surface.blit(no_selection_text_surface, no_selection_text_rect)
        
        # 加入房间按钮
        join_button_rect = pygame.Rect(right_start + 20, join_section_y + 100, 120, 40)
        if self.selected_room_id:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], join_button_rect)
            button_color = self.renderer.colors['white']
        else:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['gray'], join_button_rect)
            button_color = self.renderer.colors['black']
        
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], join_button_rect, 2)
        
        join_button_text = self.renderer.normal_font.render("Join Room", True, button_color)
        join_button_text_rect = join_button_text.get_rect(center=join_button_rect.center)
        self.renderer.virtual_surface.blit(join_button_text, join_button_text_rect)
        
        # 自定义卡组区域
        custom_deck_section_y = 500
        custom_deck_title_text = self.renderer.title_font.render("Custom Decks", True, self.renderer.colors['black'])
        custom_deck_title_rect = custom_deck_title_text.get_rect(center=(right_start + (self.renderer.design_width - right_start) // 2, custom_deck_section_y))
        self.renderer.virtual_surface.blit(custom_deck_title_text, custom_deck_title_rect)
        
        # 自定义卡组按钮
        custom_deck_button_rect = pygame.Rect(right_start + 20, custom_deck_section_y + 50, 150, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['purple'], custom_deck_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], custom_deck_button_rect, 2)
        
        custom_deck_button_text = self.renderer.normal_font.render("Custom Decks", True, self.renderer.colors['white'])
        custom_deck_button_text_rect = custom_deck_button_text.get_rect(center=custom_deck_button_rect.center)
        self.renderer.virtual_surface.blit(custom_deck_button_text, custom_deck_button_text_rect)
        
        # 渲染消息提示
        if self.message_text and self.message_timer > 0:
            self.render_message()
        
        # 缩放并显示
        self.renderer._scale_and_display()
        pygame.display.flip()
    
    def render_custom_deck_editor(self):
        """渲染自定义卡组编辑器"""
        self.renderer.virtual_surface.fill(self.renderer.colors['light_gray'])
        
        # 标题
        title_text = self.renderer.title_font.render("Custom Deck Editor", True, self.renderer.colors['black'])
        title_rect = title_text.get_rect(center=(self.renderer.design_width // 2, 50))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 右上角"读取现有卡组"按钮
        load_deck_button_rect = pygame.Rect(self.renderer.design_width - 200, 20, 180, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], load_deck_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], load_deck_button_rect, 2)
        
        load_deck_text = self.renderer.normal_font.render("Load Existing Deck", True, self.renderer.colors['white'])
        load_deck_text_rect = load_deck_text.get_rect(center=load_deck_button_rect.center)
        self.renderer.virtual_surface.blit(load_deck_text, load_deck_text_rect)
        
        # 卡组名称输入框
        name_label = self.renderer.normal_font.render("Deck Name:", True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(name_label, (50, 100))
        
        name_input_rect = pygame.Rect(200, 100, 300, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], name_input_rect)
        if self.name_input_active:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], name_input_rect, 3)
        else:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], name_input_rect, 2)
        
        name_text = self.renderer.normal_font.render(self.custom_deck_name, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(name_text, (name_input_rect.x + 5, name_input_rect.y + 5))
        
        # 卡组描述输入框
        desc_label = self.renderer.normal_font.render("Description:", True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(desc_label, (50, 140))
        
        desc_input_rect = pygame.Rect(200, 140, 400, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], desc_input_rect)
        if self.desc_input_active:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], desc_input_rect, 3)
        else:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], desc_input_rect, 2)
        
        desc_text = self.renderer.normal_font.render(self.custom_deck_description, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(desc_text, (desc_input_rect.x + 5, desc_input_rect.y + 5))
        
        # 渲染卡牌分类选择
        category_label = self.renderer.normal_font.render("Category:", True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(category_label, (50, 180))
        
        # 分类下拉菜单
        category_rect = pygame.Rect(120, 180, 120, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], category_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], category_rect, 2)
        
        category_text = self.renderer.normal_font.render(self.card_category, True, self.renderer.colors['black'])
        category_text_rect = category_text.get_rect(center=category_rect.center)
        self.renderer.virtual_surface.blit(category_text, category_text_rect)
        
        # 渲染卡牌网格
        card_registry = self.renderer.card_display.card_registry
        card_ids = list(card_registry.keys())
        
        # 按分类过滤卡牌
        if self.card_category != "All":
            filtered_card_ids = []
            for card_id in card_ids:
                card_data = card_registry[card_id]
                description = card_data.get("description", "")
                card_type = card_data.get("type", "Unknown")
                
                # 根据description判断子类型
                if card_type == "Champion":
                    if self.card_category == "Warrior" and (description.startswith("Warrior:") or not any(description.startswith(prefix) for prefix in ["Guard:", "Mage:", "Assassin:", "Rider:"])):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Guard" and description.startswith("Guard:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Mage" and description.startswith("Mage:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Assassin" and description.startswith("Assassin:"):
                        filtered_card_ids.append(card_id)
                    elif self.card_category == "Rider" and description.startswith("Rider:"):
                        filtered_card_ids.append(card_id)
                elif card_type == "Item" and self.card_category == "Item":
                    filtered_card_ids.append(card_id)
                elif card_type == self.card_category:
                    filtered_card_ids.append(card_id)
            
            card_ids = filtered_card_ids
        else:
            # All分类中排除Summoner类型的卡牌
            card_ids = [card_id for card_id in card_ids 
                       if card_registry[card_id].get("type") != "Summoner"]
        
        cards_per_row = 8
        card_width = self.renderer.card_display.card_width
        card_height = self.renderer.card_display.card_height
        card_spacing = 10
        
        grid_start_x = 50
        grid_start_y = 200
        grid_width = cards_per_row * (card_width + card_spacing) - card_spacing
        
        for i, card_id in enumerate(card_ids):
            row = i // cards_per_row
            col = i % cards_per_row
            
            card_x = grid_start_x + col * (card_width + card_spacing)
            card_y = grid_start_y + row * (card_height + card_spacing)
            
            card_data = card_registry[card_id]
            # 确保绘制函数能拿到card_id用于图片映射
            card_data_with_id = {**card_data, "card_id": card_id}
            highlighted = (self.selected_card_for_count == card_id)
            selected = (card_id in self.custom_deck_cards)
            
            self.renderer.card_display.draw_card(
                self.renderer.virtual_surface, 
                card_data_with_id, 
                card_x, 
                card_y, 
                highlighted=highlighted,
                selected=selected
            )
        
        # 渲染已选卡牌列表
        selected_cards_start_x = grid_start_x + grid_width + 50
        selected_cards_start_y = grid_start_y
        
        list_title = self.renderer.normal_font.render("Selected Cards:", True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(list_title, (selected_cards_start_x, selected_cards_start_y - 30))
        
        selected_card_height = 30
        for i, (card_id, count) in enumerate(self.custom_deck_cards.items()):
            card_y = selected_cards_start_y + i * (selected_card_height + 5)
            
            card_data = card_registry.get(card_id, {})
            card_name = card_data.get("name", card_id)
            
            # 卡牌项背景
            card_rect = pygame.Rect(selected_cards_start_x, card_y, 200, selected_card_height)
            if self.selected_card_for_count == card_id:
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['yellow'], card_rect)
            else:
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], card_rect)
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], card_rect, 1)
            
            # 卡牌名称和数量
            card_text = f"{card_name} x{count}"
            text_surface = self.renderer.small_font.render(card_text, True, self.renderer.colors['black'])
            text_rect = text_surface.get_rect(center=card_rect.center)
            self.renderer.virtual_surface.blit(text_surface, text_rect)
        
        # 右下角控制区域
        control_start_x = self.renderer.design_width - 300
        control_start_y = self.renderer.design_height - 200
        
        # 当前总数显示
        total_cards = sum(self.custom_deck_cards.values())
        total_text = f"Total Cards: {total_cards}/20"
        total_color = self.renderer.colors['green'] if total_cards == 20 else self.renderer.colors['red']
        total_surface = self.renderer.normal_font.render(total_text, True, total_color)
        self.renderer.virtual_surface.blit(total_surface, (control_start_x, control_start_y))
        
        # 数量输入框
        count_label = self.renderer.normal_font.render("Count:", True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(count_label, (control_start_x, control_start_y + 30))
        
        count_input_rect = pygame.Rect(control_start_x + 60, control_start_y + 30, 60, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], count_input_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], count_input_rect, 2)
        
        if self.card_count_input_active:
            pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], count_input_rect, 3)
        
        count_text = self.renderer.normal_font.render(self.card_count_input, True, self.renderer.colors['black'])
        self.renderer.virtual_surface.blit(count_text, (count_input_rect.x + 5, count_input_rect.y + 5))
        
        # 添加按钮
        add_button_rect = pygame.Rect(control_start_x + 130, control_start_y + 30, 50, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], add_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], add_button_rect, 2)
        
        add_text = self.renderer.small_font.render("Add", True, self.renderer.colors['white'])
        add_text_rect = add_text.get_rect(center=add_button_rect.center)
        self.renderer.virtual_surface.blit(add_text, add_text_rect)
        
        # 删除按钮
        delete_button_rect = pygame.Rect(control_start_x + 190, control_start_y + 30, 50, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], delete_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], delete_button_rect, 2)
        
        delete_text = self.renderer.small_font.render("Del", True, self.renderer.colors['white'])
        delete_text_rect = delete_text.get_rect(center=delete_button_rect.center)
        self.renderer.virtual_surface.blit(delete_text, delete_text_rect)
        
        # 保存按钮
        save_button_rect = pygame.Rect(control_start_x, control_start_y + 80, 80, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], save_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], save_button_rect, 2)
        
        save_text = self.renderer.normal_font.render("Save", True, self.renderer.colors['white'])
        save_text_rect = save_text.get_rect(center=save_button_rect.center)
        self.renderer.virtual_surface.blit(save_text, save_text_rect)
        
        # 取消按钮
        cancel_button_rect = pygame.Rect(control_start_x + 100, control_start_y + 80, 80, 40)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], cancel_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], cancel_button_rect, 2)
        
        cancel_text = self.renderer.normal_font.render("Cancel", True, self.renderer.colors['white'])
        cancel_text_rect = cancel_text.get_rect(center=cancel_button_rect.center)
        self.renderer.virtual_surface.blit(cancel_text, cancel_text_rect)
        
        # 渲染消息提示
        if self.message_text and self.message_timer > 0:
            self.render_message()
        
        # 渲染卡组列表弹出层
        if self.show_deck_list:
            self.render_deck_list_overlay()
        
        # 缩放并显示
        self.renderer._scale_and_display()
        pygame.display.flip()
    
    def render_deck_list_overlay(self):
        """渲染卡组列表弹出层"""
        # 半透明背景
        overlay_surface = pygame.Surface((self.renderer.design_width, self.renderer.design_height), pygame.SRCALPHA)
        overlay_surface.fill((0, 0, 0, 128))
        self.renderer.virtual_surface.blit(overlay_surface, (0, 0))
        
        # 弹出层窗口
        window_width = 600
        window_height = 500
        window_x = (self.renderer.design_width - window_width) // 2
        window_y = (self.renderer.design_height - window_height) // 2
        
        window_rect = pygame.Rect(window_x, window_y, window_width, window_height)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], window_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], window_rect, 3)
        
        # 标题
        title_text = self.renderer.title_font.render("Load Existing Deck", True, self.renderer.colors['black'])
        title_rect = title_text.get_rect(center=(window_x + window_width // 2, window_y + 30))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 关闭按钮
        close_button_rect = pygame.Rect(window_x + window_width - 40, window_y + 10, 30, 30)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], close_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], close_button_rect, 2)
        
        close_text = self.renderer.small_font.render("×", True, self.renderer.colors['white'])
        close_text_rect = close_text.get_rect(center=close_button_rect.center)
        self.renderer.virtual_surface.blit(close_text, close_text_rect)
        
        # 卡组列表
        list_start_y = window_y + 70
        item_height = 60
        max_items = 6  # 最多显示6个卡组
        
        if not self.custom_decks_list:
            # 没有卡组时的提示
            no_decks_text = self.renderer.normal_font.render("No custom decks found", True, self.renderer.colors['gray'])
            no_decks_rect = no_decks_text.get_rect(center=(window_x + window_width // 2, list_start_y + 100))
            self.renderer.virtual_surface.blit(no_decks_text, no_decks_rect)
        else:
            # 显示卡组列表
            for i, deck in enumerate(self.custom_decks_list[:max_items]):
                item_y = list_start_y + i * item_height
                
                # 卡组项背景
                item_rect = pygame.Rect(window_x + 20, item_y, window_width - 40, item_height - 10)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['light_gray'], item_rect)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], item_rect, 1)
                
                # 卡组名称
                name_text = self.renderer.normal_font.render(deck['title'], True, self.renderer.colors['black'])
                self.renderer.virtual_surface.blit(name_text, (item_rect.x + 10, item_rect.y + 5))
                
                # 卡组描述
                desc_text = self.renderer.small_font.render(deck['description'][:50] + "..." if len(deck['description']) > 50 else deck['description'], True, self.renderer.colors['dark_gray'])
                self.renderer.virtual_surface.blit(desc_text, (item_rect.x + 10, item_rect.y + 25))
                
                # 卡牌数量
                count_text = self.renderer.small_font.render(f"Cards: {deck['card_count']}", True, self.renderer.colors['blue'])
                self.renderer.virtual_surface.blit(count_text, (item_rect.x + 10, item_rect.y + 40))
                
                # 加载按钮
                load_button_rect = pygame.Rect(item_rect.right - 120, item_rect.y + 10, 50, 30)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['green'], load_button_rect)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], load_button_rect, 1)
                
                load_text = self.renderer.small_font.render("Load", True, self.renderer.colors['white'])
                load_text_rect = load_text.get_rect(center=load_button_rect.center)
                self.renderer.virtual_surface.blit(load_text, load_text_rect)
                
                # 删除按钮
                delete_button_rect = pygame.Rect(item_rect.right - 60, item_rect.y + 10, 50, 30)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['red'], delete_button_rect)
                pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['black'], delete_button_rect, 1)
                
                delete_text = self.renderer.small_font.render("Del", True, self.renderer.colors['white'])
                delete_text_rect = delete_text.get_rect(center=delete_button_rect.center)
                self.renderer.virtual_surface.blit(delete_text, delete_text_rect)
    
    def render_game_over(self):
        """渲染游戏结束界面"""
        self.renderer.virtual_surface.fill(self.renderer.colors['dark_gray'])
        
        # 游戏结束标题
        title_text = self.renderer.title_font.render("Game Over", True, self.renderer.colors['white'])
        title_rect = title_text.get_rect(center=(self.renderer.design_width // 2, 200))
        self.renderer.virtual_surface.blit(title_text, title_rect)
        
        # 显示游戏结果
        if self.game_over_result:
            winner = self.game_over_result.get('winner', 'Unknown')
            message = self.game_over_result.get('message', 'Game ended')
            
            # 获胜者信息
            winner_text = f"Winner: {winner}"
            winner_surface = self.renderer.normal_font.render(winner_text, True, self.renderer.colors['yellow'])
            winner_rect = winner_surface.get_rect(center=(self.renderer.design_width // 2, 280))
            self.renderer.virtual_surface.blit(winner_surface, winner_rect)
            
            # 游戏结束消息
            message_surface = self.renderer.normal_font.render(message, True, self.renderer.colors['white'])
            message_rect = message_surface.get_rect(center=(self.renderer.design_width // 2, 320))
            self.renderer.virtual_surface.blit(message_surface, message_rect)
        
        # 返回房间选择按钮
        return_button_rect = pygame.Rect(self.renderer.design_width // 2 - 100, 400, 200, 50)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['blue'], return_button_rect)
        pygame.draw.rect(self.renderer.virtual_surface, self.renderer.colors['white'], return_button_rect, 2)
        
        return_text = self.renderer.normal_font.render("Return to Room Selection", True, self.renderer.colors['white'])
        return_text_rect = return_text.get_rect(center=return_button_rect.center)
        self.renderer.virtual_surface.blit(return_text, return_text_rect)
        
        # 渲染消息提示
        if self.message_text and self.message_timer > 0:
            self.render_message()
        
        # 缩放并显示
        self.renderer._scale_and_display()
        pygame.display.flip()


async def main():
    """主函数"""
    game = CardGame()
    await game.run()


if __name__ == "__main__":
    asyncio.run(main())
